C++ 如何从模板生成具有常量或非常量成员函数的类?

C++ 如何从模板生成具有常量或非常量成员函数的类?,c++,templates,c++11,C++,Templates,C++11,我有以下模板: template<typename Signature> class TypeErasedFunctor; template<typename R, typename... Args> class TypeErasedFunctor<R(Args...)> { public: virtual R operator()(Args... args) = 0; }; 模板 类类型擦除函数; 模板 类类型擦除函数 { 公众: 虚拟R运算符

我有以下模板:

template<typename Signature>
class TypeErasedFunctor;

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

    virtual R operator()(Args... args) = 0;
};
模板
类类型擦除函数;
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)=0;
};
它可用于为以下函数生成接口类:

使用信号量函数=type橡皮擦函数

可以看出,成员函数
operator()
是非常量的。我想问以下问题-除了这两个选项外,是否有其他选项可以选择是否创建常量或非常量变量:

  • 使用SFINAE(可能与
    std::enable_if
    )和模板的附加参数
  • 使用单独的模板
    constTypeReasedFunctor
可以在重载的同一对象上同时使用运算符()的(常量和非常量)版本。但是,如果您想在声明对象时轻松地只选择一个对象,可以使用以下方法:

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&)>;
模板
类类型擦除函数;
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)常量=0;
};
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)=0;
};
模板
使用信号量函数=type橡皮擦函数;
稍后,在客户端代码中,您可以使用剩余的泛型参数选择:

SemaphoreFunctor<true> object_with_const_op;
SemaphoreFunctor<false> object_with_no_const_op;
SemaphoreFunctor object_,带有常量;
无常量的信号量函数对象;
可以在重载的同一对象上同时使用运算符()的(常量和非常量)版本。但是,如果您想在声明对象时轻松地只选择一个对象,可以使用以下方法:

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&)>;
模板
类类型擦除函数;
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)常量=0;
};
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)=0;
};
模板
使用信号量函数=type橡皮擦函数;
稍后,在客户端代码中,您可以使用剩余的泛型参数选择:

SemaphoreFunctor<true> object_with_const_op;
SemaphoreFunctor<false> object_with_no_const_op;
SemaphoreFunctor object_,带有常量;
无常量的信号量函数对象;
可以在重载的同一对象上同时使用运算符()的(常量和非常量)版本。但是,如果您想在声明对象时轻松地只选择一个对象,可以使用以下方法:

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&)>;
模板
类类型擦除函数;
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)常量=0;
};
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)=0;
};
模板
使用信号量函数=type橡皮擦函数;
稍后,在客户端代码中,您可以使用剩余的泛型参数选择:

SemaphoreFunctor<true> object_with_const_op;
SemaphoreFunctor<false> object_with_no_const_op;
SemaphoreFunctor object_,带有常量;
无常量的信号量函数对象;
可以在重载的同一对象上同时使用运算符()的(常量和非常量)版本。但是,如果您想在声明对象时轻松地只选择一个对象,可以使用以下方法:

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&)>;
模板
类类型擦除函数;
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)常量=0;
};
模板
类类型擦除函数
{
公众:
虚拟R运算符()(Args…Args)=0;
};
模板
使用信号量函数=type橡皮擦函数;
稍后,在客户端代码中,您可以使用剩余的泛型参数选择:

SemaphoreFunctor<true> object_with_const_op;
SemaphoreFunctor<false> object_with_no_const_op;
SemaphoreFunctor object_,带有常量;
无常量的信号量函数对象;

对于这个特殊问题,只需将其设为
常量
,因为按照惯例,函子应该是无状态的,因此是不可变的/const。这就是
std::function
所做的。通过将非常量函子作为
可变的
数据成员,您总是可以绕过派生类中的常量。@MikaelPersson-好吧,关于“无状态”的部分我不能同意(如果函子应该是无状态的,与普通函数相比有什么好处?),但是您能详细说明一下吗“将非常量函子保持为可变数据成员”?我必须承认,问题的动机是需要修改从该模板派生的对象的内容(在某些情况下),而不是使用
操作符()const
在非const对象上。无状态是指对函数的任意两个后续调用将具有相同的效果和结果。通常,函数作为回调函数或算法的辅助函数(例如谓词、比较函数等)传递,其中未定义调用函子的频率和确切时间,在该上下文中,如果它是无状态的,则更可取。然而,无状态并不意味着“无参数”,这就是函子(可调用obj)的位置比函数指针更好。通常,你需要一个参数化的函子,而不是有状态的函子。至于详细说明“将非常量函子作为可变数据成员"... 我不知道我能说多少,这很清楚。如果有时必须修改
操作符()
中某个特定派生类的一些数据成员,那么在这些罕见的情况下,您只需使用
mutable
。如果问题是您不知道可变关键字,请阅读。@MikaelPersson-我现在明白了。以前我认为你的意思是我可以将基类派生的对象作为其他对象的可变成员保留,这没有多大意义(;对于这个特殊的问题,只需将其设为
const
,因为按照惯例,函子应该是无状态的,因此是不可变的/const。这就是
std::function
所做的。通过将非const函子作为
可变的
数据成员,您可以始终避免派生类中的常量。@MikaelPers儿子-好吧,关于“无状态”的部分我不能同意(如果函子应该是无状态的,与普通的乐趣相比有什么好处