2014-12-10 62 views
0

我有下列模板:如何从模板中使用const或非const成员函数生成类?

template<typename Signature> 
class TypeErasedFunctor; 

template<typename R, typename... Args> 
class TypeErasedFunctor<R(Args...)> 
{ 
public: 

    virtual R operator()(Args... args) = 0; 
}; 

它可被用于产生接口类为这样函子:

using SemaphoreFunctor = TypeErasedFunctor<int(Semaphore&)>;

如可以看到的成员函数operator()是非常量。我想问以下问题 - 是否有任何选项来选择是否const或非const变量应该不是这两个产生的其它:

  • 使用SFINAE(可能与std::enable_if<>)和模板的其他参数,
  • 使用单独的模板ConstTypeErasedFunctor
+1

对于这个特殊的问题,只是使它成为'const',因为按照惯例,函数应该是无状态的,因此,不可变/常量。这就是'std :: function'所做的。您可以通过将非const函数作为“可变”数据成员来避开派生类中的常量。 – 2014-12-10 21:52:31

+0

@MikaelPersson - 那么,关于“无状态”的部分,我不能同意(如果函数应该是无状态的,与纯函数相比有什么收获?),但是您能否详细说明“将非const函数作为可变数据成员“?我必须承认,问题的动机是需要修改从此模板派生的对象的内容(在某些情况下),而不是在非const对象上使用'operator()const'。 – 2014-12-10 22:00:08

+0

无状态意味着任何两个随后的函数调用都会产生相同的效果和结果。通常情况下,函数作为回调函数或作为算法的辅助函数传递(例如,谓词,比较函数等),其中未定义函数调用的频率和时间,在这种情况下,它更可取如果它是无状态的。然而,无状态并不意味着“无参数”,这就是functor(callable obj)比函数指针更好的地方。通常,你需要一个*参数化的函子,而不是*有状态的*函子。 – 2014-12-10 23:10:23

回答

3

可以兼得(常量和没有常)相同的对象重载运营商的版本()。但是,如果你想轻松地只有一个选择申报对象时,你可以使用类似的东西:

template<bool b, typename Signature> 
class TypeErasedFunctor; 

template<typename R, typename... Args> 
class TypeErasedFunctor<true,R(Args...)> 
{ 
    public: 
     virtual R operator() (Args... args) const = 0; 
}; 

template<typename R, typename... Args> 
class TypeErasedFunctor<false,R(Args...)> 
{ 
    public: 
     virtual R operator()(Args... args) = 0; 
}; 

template<bool b> 
using SemaphoreFunctor = TypeErasedFunctor<b,int(Semaphore&)>; 

后来,在客户端代码,你可以用剩下的一般的参数选择:

SemaphoreFunctor<true> object_with_const_op; 
SemaphoreFunctor<false> object_with_no_const_op;