我在linux下编写了一个Signal / Slot库(Codeproject article here),用Clang 3.5和GCC4.9编译。它在两个编译器上都没有警告地编译(也在版本3.4和4.8上)。当我把它全部工作,并在网上发布文章时,不久我得到的投诉是它不能在MSVC上工作。 (Visual Studio Express 2013?对不起,我不熟悉版本控制系统。)我将它安装在虚拟机中以便自己查看,发现它不会编译以下内容:
template <typename Signature>
struct RemoveCV;
template <typename R, typename ... Args>
struct RemoveCV<T, R (Args...)>
{
using Type = R(Args...);
};
template <typename R, typename ... Args>
struct RemoveCV<T, R(Args...) const>
{
using Type = R(Args...);
};
// more specializations for volatile and const volatile
// Usage:
template <typename Signature_>
struct Function
{
using Signature = RemoveCV<Signature_>::Type;
};
// both Function<void()> and Function<void() const> now have
// the same Signature: void()
原因是R(Args ...)
不是成员函数,因此它不能具有const
限定符。
虽然在非成员函数上有一个const
限定符是没有意义的,但我相信我在某处阅读(这里是SO,包括标准的引用),只要它不受实际功能的约束,它就被允许。即 允许作为独立类型。不幸的是我似乎无法找到那个线程......
我只是想知道在这个场合谁是对的:MSVC或GCC + Clang,以及关于像void() const
这样的独立功能签名的标准。
答案 0 :(得分:5)
嗯,我相信你(和海湾合作委员会和Clang)似乎是正确的,就标准所说的而言。来自§8.3.5/ 6 (在N3376中),(强调我的):
cv-qualifier-seq 或 ref-qualifier 只能属于:
- 非静态成员函数的函数类型
- 指向成员的指针引用的函数类型,
- 函数typedef声明或别名声明的顶级函数类型
- type-parameter(14.1)的默认参数中的type-id,或
- type-parameter(14.2)的template-argument的type-id。