如何将functor用作类模板中的成员?

时间:2014-02-04 09:18:18

标签: c++ templates c++11 stl functor

我试图在类模板中使用仿函数作为std::function对象。以下是我到目前为止所做的工作。

//! the functor class template
template<typename T>
struct func
{
    void operator ()(T t)
    {
        std::cout << t << "\n";
    }
};

//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
    std::function<void(T)> bar = func<T>();
};


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

有人抱怨

error: conversion from 'func<int>' to non-scalar type 'std::function<void(int)>' requested
 struct Foo
        ^

有可能这样做吗?如何解决?

3 个答案:

答案 0 :(得分:2)

您可以将其设置为静态并在类范围外初始化它,或者在构造函数中初始化它。在GCC 4.7.2上进行了测试。

template<typename T>                                                                                
struct Foo                                                                                          
{                                                                                                   
    static std::function<void(T)> bar;                                                                 
};                                                                                                  

template <typename T>                                                                               
std::function<void(T)> Foo<T>::bar = func<T>(); 

修改

在C ++ 11中,您还可以使用大括号初始化:

std::function<void(T)> bar { func<T>() };

答案 1 :(得分:1)

在你的情况下,std :: function是可选的,使用直接函子本身。

//! the functor class template
template<typename T>
struct func
{
    void operator ()(T t)
    {
        std::cout << t << "\n";
    }
};

//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
    //std::function<void(T)> bar = func<T>(); <-- **removed, because std::function isn't cheap as func<T>**.
    func<T> bar;//default initialized itself.
};


int main()
{
    Foo<int> foo;
    foo.bar(24);//prints 24.
    return 0;
}

编辑:  通常情况下,将模板从struct declration移动到运算符,即:

struct func
{
   template< typename T >
   void operator()(T t ) const { std::cout << t << '\n'; }
};

struct Foo
{
    func m_func;
};

int main(){
   Foo f;
   f.m_func(24); // prints 24
   f.m_func("hello world"); // prints "hello world"
   f.m_func(3.143); // prints 3.143
   // and etc.,
};

在c ++ 14中,std :: less&lt;&gt ;,std :: greater&lt;&gt;和更多其他仿函数模板关键字移动到运算符声明,而不是结构声明,这有助于更多的通用比较。

Edit2:您可以使用以下技术:

struct func{  
  template< typename T > void operator()(T t) const{ std::cout << t << '\n';} 
};

template< typename T, typename Functor> // Functor as template
struct Foo
{
    Functor m_Functor; //--> functor member
    T       m_Data; // or something else.
};

// create `makeFoo`  for auto deduced functor type.
template< typename T, typename Functor>
Foo<T,Functor>  makeFoo(Functor f, T t ) { return {f,t}; }

int print(int i, int j){ std::cout << i+j << '\n' ;}

int main()
{
    auto foo = makeFoo(24, func{} );
    // use foo

    auto foo2 = makeFoo("hello", std::bind(print, 2, _1) ); 
   // use foo2
}

答案 2 :(得分:1)

在非静态数据成员初始值设定项中使用std :: function的不同方法

#include <functional>
#include <iostream>

#define ENABLE_CONVERSION 1

template<typename T>
struct func
{
    void operator ()(T t)
    {
        std::cout << "Function: " << t << "\n";
    }

    #if ENABLE_CONVERSION
    // FIX: error: conversion from ‘func<int>’ to non-scalar type
    //      ‘std::function<void(int)>’ requested
    operator std::function<void(T)> () { return std::function<void(T)>(*this); }
    #endif
};

template<typename T>
struct Foo
{
    std::function<void(T)> bar0 = std::function<void(T)>(func<T>());
    std::function<void(T)> bar1{func<T>()};
    // Error without ENABLE_CONVERSION
    std::function<void(T)> bar2 = func<T>();
    static std::function<void(T)> bar3;

    void operator() () {
        bar0(0);
        bar1(1);
        bar2(2);
        bar3(3);
    }
};

template<typename T>
std::function<void(T)> Foo<T>::bar3 = func<T>();

template<typename T>
void goo() {
    // This compiles without ENABLE_CONVERSION:
    // What is the difference to non-static data member initializers ?
    std::function<void(T)> g = func<T>();
    g(4);
}

int main()
{
    Foo<int> foo;
    foo();
    goo<int>();
    return 0;
}

其他问题

我试图找到变量brace-or-equal-initializer之间的差异 和非静态数据成员brace-or-equal-initializer。我一无所获。

之间有什么区别
std::function<void(T)> bar2 = func<T>();

std::function<void(T)> g = func<T>();

当ENABLE_CONVERSION为零时?