简体   繁体   English

C ++重载函数作为模板参数

[英]C++ overloaded function as template argument

the simplified version of my code is here 我的代码的简化版本在这里

int foo(int x)
{
  return x;
}

int foo(int x, int y)
{
  return x+y;
}

template<typename unary_func>
int bar(int k, unary_func f)
{
  return f(k);
}

int main()
{
  bar(3, foo);
  return 0;
}

Is there a way to tell the compiler what I want to pass as argument is the first `foo'? 有没有办法告诉编译器我要传递什么,因为参数是第一个`foo'?

You can give an explicit template argument: 您可以提供显式模板参数:

bar<int(int)>(3, foo);

or cast the ambiguous function name to a type from which the template argument can be deduced: 或者将不明确的函数名称转换为可以推导出模板参数的类型:

bar(3, static_cast<int(*)(int)>(foo));

or wrap it in another function (or function object) to remove the ambiguity 或将其包装在另一个函数(或函数对象)中以消除歧义

bar(3, [](int x){return foo(x);});

I handle this problem with the following macro: 我使用以下宏处理此问题:

#define LIFT(fname) \
[] (auto&&... args) -> decltype (auto) \
{ \
    return fname (std::forward <decltype (args)> (args)...); \
}

Given your definitions of foo and bar , you can say 鉴于你对foobar定义,你可以说

int main()
{
    bar(3, LIFT(foo));
    return 0;
}

and the correct overload will be selected. 并选择正确的过载。 This uses some features of C++14, namely generic lambdas and decltype(auto) . 这使用了C ++ 14的一些功能,即通用lambdas和decltype(auto) If you're using C++11, you can get more or less the same effect with a little more work: 如果你正在使用C ++ 11,你可以通过更多的工作获得或多或少相同的效果:

#define DECLARE_LIFTABLE(NAME) \
struct NAME##_lifter \
{ \
    template <typename... Args> \
    auto operator () (Args&&... args) -> decltype (NAME (std::forward <Args> (args)...)) \
    { \
        return NAME (std::forward <decltype (args)> (args)...); \
    } \
}
#define LIFT(NAME) (NAME##_lifter {})

DECLARE_LIFTABLE(foo);
int main()
{
    bar(3, LIFT(foo));
    return 0;
}

If you're using C++98, you're basically stuck with a cast to the appropriate function pointer type. 如果您正在使用C ++ 98,那么您基本上会使用强制转换为适当的函数指针类型。

No, you can't, because you are calling the function always with only one argument, you need a type with only one argument. 不,你不能,因为你总是只用一个参数调用函数,你需要一个只有一个参数的类型。 Instead, you can use template by value (no typename or class) 相反,您可以按值使用模板(无类型名称或类)

One argument: 一个论点:


int foo(int x)
{
    return x;
}

int foo(int x, int y)
{
    return x+y;
}

typedef int (*foo_fcn)(int);

template<foo_fcn unary_func>
int bar(int k)
{
    return unary_func(k);
}

int main()
{
    bar<foo>(3);
    return 0;
}

Two arguments: 两个论点:


int foo(int x)
{
    return x;
}

int foo(int x, int y)
{
    return x+y;
}

typedef int (*foo_fcn)(int, int);

template<foo_fcn unary_func>
int bar(int k)
{
    return unary_func(k, k);
}

int main()
{
    bar<foo>(3);
    return 0;
}

Both: 都:


int foo(int x) // first foo
{
    return x;
}

int foo(int x, int y) // second foo
{
    return x+y;
}

typedef int (*foo_fcn)(int);
typedef int (*foo_fcn_2)(int, int);

template<foo_fcn unary_func>
int bar(int k)
{
    return unary_func(k);
}

template<foo_fcn_2 unary_func>
int bar(int a, int b)
{
    return unary_func(a, b);
}


int main()
{
    bar<foo>(3,1); // compiler will choose first foo
    bar<foo>(4); // compiler will choose second foo
    return 0;
}

Yes: 是:

bar(3, static_cast<int(*)(int)>(&foo));

or: 要么:

bar<int(*)(int)>(3, &foo);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM