类模板:为什么我不能为 void 类型专门指定一个方法? [英] Class template: why can't I specialize a single method for void type?

查看:30
本文介绍了类模板:为什么我不能为 void 类型专门指定一个方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类模板:

template <typename Argument> class Signal
{
    void invoke(Argument arg) {}
};

现在我想调用没有参数的信号(意思是 void 参数).我假设我可以将整个类专门化为 void 并且它会编译.但是课上代码很多,不想重复.我只想专注于任何必要的事情.所以我尝试添加:

Now I want to invoke signals without parameter (meaning void parameter). I assume I could specialize the whole class for void and it would compile. But there's a lot of code in the class, I don't want to duplicate it. I want to only specialize whatever neccessary. So I try adding:

// void specialization
template<> 
void Signal<void>::invoke()
{

}

并得到一个错误:

错误 C2244:'Signal::invoke':无法匹配函数对现有声明的定义

error C2244: 'Signal::invoke' : unable to match function definition to an existing declaration

这是为什么?

相同的代码适用于除 void 之外的任何类型.

The same code works for any type other than void.

推荐答案

此模板的专业化:

template <typename Argument> class Signal
{
    void invoke(Argument arg) {}
};

应该是:

template<> 
void Signal<void>::invoke(void arg)
{

}

这是非法的,因为你不能有一个 void 对象.

which is illegal because you can't have a void object.

做你想做的一种方法是使用重载来声明两个调用方法,并使用一些模板技巧(我相信这个技巧被称为 SFINAE) 仅允许基于您的类模板参数的正确重载可用:

One way of doing what you want is to use overloading to declare both invoke methods, and use some templating tricks (I believe this one is called SFINAE) to only allow the correct overload available based on your class template argument:

template <typename Argument> class Signal
{
public:
    static constexpr bool IsVoid = is_same<Argument, void>::value;

    template <typename T = Argument, typename = typename std::enable_if< !IsVoid && is_same<Argument, T>::value>::type >
    void invoke(T arg) {
        // only available for non-void types
    }

    template <typename T = Argument, typename = typename std::enable_if< IsVoid >::type >
    void invoke() {
        // only available for void class specialization
    }
}


Signal<void> sv;
Signal<int> si;

sv.invoke(); // OK
si.invoke(1); // OK

sv.invoke(1); // NOT OK
sv.invoke("s"); // NOT OK
si.invoke(); // NOT OK
si.invoke("s"); // NOT OK

您可以在此处找到有关 enable_if 用法的更多信息:std::enable_if 有条件地编译成员函数为什么我应该避免在函数签名中使用 std::enable_if.

You can find more about the usage of enable_if here: std::enable_if to conditionally compile a member function, Why should I avoid std::enable_if in function signatures.

这篇关于类模板:为什么我不能为 void 类型专门指定一个方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆