【问题标题】:C++ check if a template argument is a function of a specific typeC++ 检查模板参数是否是特定类型的函数
【发布时间】:2021-12-26 05:31:19
【问题描述】:

我有以下函数用作二分法

template <typename T>
float bisect(T value, float min, float max, float tol) {
    constexpr bool is_function1 = is_numeric_function1<T>::value;
    constexpr bool is_function2 = is_numeric_function2<T>::value;

    std::cout << is_function1 << " " << is_function2 << std::endl;
    
    if(is_function1) {
        ...
    } else if(is_function2) {
        ...
    }

...
}

一开始,我想检查第一个参数是float(float) 还是float(float, float) 类型的函数,所以我有以下模板

template<typename T, typename = T> struct is_numeric_function1 : std::false_type {};
template<typename T>
struct is_numeric_function1 <typename T,
    std::enable_if_t<std::is_same<T, float(float)>::value, T>
> : std::true_type {};

template<typename T, typename = T> struct is_numeric_function2 : std::false_type {};
template<typename T>
struct is_numeric_function2 <typename T,
    std::enable_if_t<std::is_same<T, float(float, float)>::value, T>
> : std::true_type {};

对于这样的功能

float f2(float v1, float v2) {
    return std::pow(v1, 2) + std::pow(v2, 2);
}

还有这样的电话

std::cout << bisect(f2, 0., 100, 1.)
    << std::endl;

输出总是

0 0
<result>

我怎样才能让它工作?

【问题讨论】:

  • is_numeric_function1 有效吗?另外,请说明你是如何打电话给bisect的。
  • 这些功能都不起作用,我也更新了问题。
  • 我不能reproduce
  • 你真的要推断结构吗?您可以使用 arg enum {fun1, fun2} type 创建 1 个结构并在构造函数中设置类型。

标签: c++ function templates


【解决方案1】:

只要您不将有状态对象传递给您的bisect(我在您的示例中没有看到),简单的函数指针和重载就可以完成这项工作(我已经简化了 sn-p 以专注于主要部分):

float bisect(float fn(float)) { return fn(1); }
float bisect(float fn(float, float)) { return fn(1, 2); }

float f1(float x) { return x; }
float f2(float x, float y) { return x + y; }

int main() { std::cout << bisect(f1) << '\n' << bisect(f2) << '\n'; }

但是,如果您确实需要 T 类似于有状态的 lambda,只需 constrain 更需要的重载;在下面的例子中,我假设它是float(float, float):

float bisect(auto&& fn) { return fn(1.f); }
float bisect(auto&& fn) requires requires { fn(1.f, 2.f); } { return fn(1.f, 2.f); }

int main() {
  std::cout << bisect([state = 42](float x) { return x; }) << '\n' << bisect(f2) << '\n';
}

注意:我建议不限制优先级较低的重载,以允许传递像这样的重载功能对象:

struct Overloaded {
  float operator(float) { return 42; }
  float operator(float, float) { return 42; }
} bisect_me_and_get_ambiguity;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多