【问题标题】:Convert overloaded function to template functor将重载函数转换为模板函子
【发布时间】:2014-04-28 11:35:24
【问题描述】:

我有一些重载函数,例如

int a(int) {/*...*/}
float a(float) {/*...*/}
/* ... */
int b(int) {/*...*/}
float b(float) {/*...*/}
/* ... */

我的目标是将这些函数包装到一个仿函数对象中:

template <typename T>
struct func_a {
    auto T operator()(T t) -> decltype(a(t)) {return a(t);}
};

有没有办法将上述模板结构定义为以重载函数作为参数的其他模板?像这样的:

template </* pointer to an overloaded function f */>
struct create_functor {
    template <typename T>
    struct func {
        auto operator()() -> decltype(f(t)) {return f(t);}
    }
};

所以我可以在编译时生成结构,如下所示:

typedef create_functor<a>::func<int> func_a_int;
typedef create_functor<a>::func<float> func_a_float;
typedef create_functor<b>::func<int> func_a_int;
typedef create_functor<b>::func<float> func_a_float;

【问题讨论】:

  • auto T operator(T t) -&gt; decltype(a(t)) {return a(t);}...你的意思是auto operator()(T t) -&gt; decltype(a(t)) { return a(t); }吗?
  • 我想知道:你想完成什么?
  • 简而言之,多维矩阵广播。执行它的函数有一些符号:template &lt;class &lt;class...&gt; class Func, typename ...Matrices&gt; /*...*/ broadcast(const Matrices &amp;...m) {/*...*/} 因此我可以用Func&lt;Matrices::value_type ...&gt;() 实例化函子对象。这对仿函数很有效,但我需要某种方法来绑定重载函数。我有一些宏解决方案,但我只是想知道是否有使用模板的方法。
  • 请注意,我提出的解决方案只是为了方便而使用宏。也可以为每个重载函数手动设置模板化重载。
  • 您不能将重载的函数名称作为模板参数传递。您必须提供消除重载歧义的上下文。 ComicSansMS 反转模板参数顺序以提供明确的上下文。

标签: c++ c++11 functor


【解决方案1】:

您可以为每个函数定义一个重载集,例如:

int a(int i) {return 2*i;} 
float a(float d) {return 3*d;} 

#define overload_set(f, f_set) \
    struct f_set  { \
        template <typename... Args> \
        auto operator()(Args&&... args) \
            -> decltype(f(std::forward<Args>(args)...)) \
        { \
            return f(std::forward<Args>(args)...); \
        } \
    } 

overload_set(a, a_set);
// more overload_set here...

使用重载集而不是函数指针使“create_functor”实现变得简单:

template <typename OverloadSet>
struct create_functor {
    template <typename... Args>
    struct func {
        auto operator()(Args... args) 
            -> decltype(OverloadSet{}(args...)) 
        {
            return OverloadSet{}(args...);
        }
    };
};

create_functor<a_set>::func<int> func_a_int; // Note: no need for typedef here
create_functor<a_set>::func<float> func_a_float;

int main()
{
   std::cout << func_a_int(2) << std::endl;
   std::cout << func_a_float(3.) << std::endl;
}

【讨论】:

    【解决方案2】:

    只要不同重载的签名与您的问题一样统一,就可以通过使用函数指针值作为模板参数来完成:

    template<typename T>
    struct create_functor {
        template<T(*fct)(T)>
        struct functor {
            T operator()(T n) { return fct(n); }
        };
    };
    
    create_functor<int>::functor<a> func_a_int;
    create_functor<float>::functor<a> func_a_float;
    
    std::cout << func_a_int(42) << func_a_float(3.14f) << std::endl;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      • 2017-12-24
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多