【发布时间】:2012-11-20 07:52:10
【问题描述】:
我正在使用一些 SFINAE 功能;当前位于必须在 Linux 和 Windows 中运行的应用程序的一部分中;编译器选择是用于 Windows 应用程序的 MSVC (Visual Studio 2010 10.0) 和用于 Linux 应用程序的 GCC 4.4.5。
我必须检查某个给定对象是否提供了一些函数来执行自定义序列化并调用此函数,或者在未提供自定义序列化方法时执行简单的memcpy 和sizeof(Object)。
问题是一段代码在 MSVC 中编译时没有警告或错误,但在使用 GCC 编译时,代码如下:
template
<
typename Type,
typename Return,
typename Parameter,
Return (Type::*Pointer)(Parameter) const
> struct sMemberMethodConst { };
template
<
typename Type,
typename Return,
typename Parameter,
Return (Type::*)(Parameter)
> struct sMemberMethod { };
template<typename T> struct sMemberMethodChecker
{
template <typename Type> static char HasCustomSizeMethod(sMemberMethodConst<Type, size_t, void, &Type::Size> *);
template <typename Type> static long HasCustomSizeMethod(...);
template <typename Type> static char HasSerializeMethod(sMemberMethodConst<Type, size_t, void * const, &Type::Serialize> *);
template <typename Type> static long HasSerializeMethod(...);
template <typename Type> static char HasDeserializeMethod(sMemberMethod<Type, size_t, const void * const, &Type::Deserialize> *);
template <typename Type> static long HasDeserializeMethod(...);
// Other specific method checks...
enum
{
HAS_CUSTOM_SIZE_METHOD = (sizeof(HasCustomSizeMethod<T>(0)) == sizeof(char)),
HAS_SERIALIZE_METHOD = (sizeof(HasSerializeMethod<T>(0)) == sizeof(char)),
HAS_DESERIALIZE_METHOD = (sizeof(HasDeserializeMethod<T>(0)) == sizeof(char)),
IS_CUSTOM = HAS_CUSTOM_SIZE_METHOD &&
HAS_SERIALIZE_METHOD &&
HAS_DESERIALIZE_METHOD,
// Other 'shortcuts'...
};
我在使用 GCC 编译时遇到的错误是:
invalid parameter type 'void' in declaration template<class Type, class Return, class Parameter, Return (Type::* Pointer)(Parameter)const>
在struct sMemberMethodChecker 的第一行。我很确定我没有遗漏typenames 也没有放错词,但我不明白为什么我会收到错误并且不明白错误。
我知道 MSVC 的标准松懈,而 GCC 非常符合标准,所以我想知道问题是否出在允许 愚蠢代码的 MSVC 方面!
以下是问题:
- 为什么我在
struct sMemberMethodChecker中收到invalid parameter type 'void'错误?。 - 为什么代码在 MSVC 中有效但在 GCC 中无效?。
- 此代码是否不标准?
- SFINAE 诡计是 C++11 独有的吗?
【问题讨论】:
-
是否允许
const void * const?您是在告诉编译器您有一个const void类型的对象。但是无论如何都不能修改空隙AFAIK?如果您尝试void * const,会发生什么? -
好问题。似乎 GCC 不接受
template < typename Type, typename Return, typename Parameter, Return (Type::*)(void) > struct sMemberMethod { };作为参数。然而,MSVC 对此持开放态度。 -
我相信 iammilind 是对的。与 C 不同,C++ 不允许在函数的参数列表中使用
void。这是因为在 C 中,f()是一个没有原型的函数(= 未指定参数),而在 C++ 中,f()是一个没有参数的函数。
标签: c++ templates visual-c++ gcc sfinae