【问题标题】:C++ overloaded function as template argumentC++ 重载函数作为模板参数
【发布时间】:2014-09-16 14:24:52
【问题描述】:

我的代码的简化版本在这里

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'?

【问题讨论】:

    标签: c++ templates overloading


    【解决方案1】:

    你可以给出一个显式的模板参数:

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

    或将模棱两可的函数名称转换为可以从中推断出模板参数的类型:

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

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

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

    【讨论】:

    • 实际上,就我而言, foo 是第四个参数。那么最好的方法是 static_cast?
    【解决方案2】:

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

    #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,那么您基本上会被强制转换为适当的函数指针类型。

    【讨论】:

    【解决方案3】:

    不,你不能,因为你总是用一个参数调用函数,你需要一个只有一个参数的类型。相反,您可以按值使用模板(没有类型名或类)

    一个论点:

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

    【讨论】:

      【解决方案4】:

      是的:

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

      或:

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

      【讨论】:

      • bar&lt;int(int)&gt;(3, foo)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多