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

18

我代码的简化版本在这里

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;
}

有没有办法告诉编译器我想传递的参数是第一个 `foo'?

4个回答

13

您可以给出显式的模板参数:

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

或将不明确的函数名称强制转换为一个类型,从而可以推导出模板参数:

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

或者将其包装在另一个函数(或函数对象)中以消除歧义。

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

实际上,在我的情况下,foo是第四个参数。那么最好的方法是使用static_cast吗? - Rankaba

7
我将使用以下宏来解决这个问题:

我用以下宏来处理这个问题:

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

在您定义了 foobar 后,您可以这样说:

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

并且将选择正确的重载。这使用了一些C++14的特性,即通用lambda和decltype(auto)。如果您正在使用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;
}

如果你正在使用C++98,那么你基本上只能使用适当的函数指针类型转换。


1
https://florianjw.de/en/passing_overloaded_functions.html 提供了第一个宏的更多解释。 - phimuemue

4
不行,因为你总是只传递一个参数调用该函数,你需要一个只有一个参数的类型。你可以使用按值模板(没有typename或class)。
一个参数:

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;
}

两个参数:


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;
}

双方:


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;
}

1

是的:

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

或者:

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

4
或者 bar<int(int)>(3, foo) - Xeo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接