Mic*_*l G 5 c++ templates sfinae visual-c++ c++11
遇到SFINAE问题.我需要能够确定Type是否具有成员函数operator->,无论其返回类型如何.示例如下.
这个类在测试者中.它定义了operator - >(),返回类型为X*.因此我不知道'X'到处硬编码是什么.
template <class X>
class PointerX
{
...
X* operator->() const;
...
}
Run Code Online (Sandbox Code Playgroud)
此类尝试确定传入的T是否具有方法operator-> defined; 无论operator-> return类型是什么.
template<typename T>
struct HasOperatorMemberAccessor
{
template <typename R, typename C> static R GetReturnType( R ( C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, decltype( GetReturnType(&U::operator->)), &U::operator-> >*);
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
Run Code Online (Sandbox Code Playgroud)
除了operator-> return类型必须是'Object'之外,这个类与上面完全相同.
template<typename T>
struct HasOperatorMemberAccessorOBJECT
{
template <typename R, typename C> static R GetReturnType( R ( C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, Object*, &U::operator-> >*); // only change is we hardcoded Object as return type.
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
Run Code Online (Sandbox Code Playgroud)
结果:
void main()
{
HasOperatorMemberAccessor<PointerX<Object>>::Test<PointerX<Object>>(0); // fails ::value is false; Test => Test(...)
HasOperatorMemberAccessorOBJECT<PointerX<Object>>::Test<PointerX<Object>>(0); // works! ::value is true; Test => Test(SFINAE<>*)
}
Run Code Online (Sandbox Code Playgroud)
HasOperatorMemberAccessor无法找到PointX的成员函数"Object operator - >()const".所以它使用Test的通用版本Test(...).
但是,HasOperatorMemberAccessorOBJECT能够找到PointX的"Object operator - >()const".因此它使用Test专业版测试(SFINAE*).
两者都应该能够找到"Object operator - >()const"方法; 因此两者都应该使用Test的专业版Test(SFINAE*); 因此HasOperatorMemberAccessor> :: value应为true.
HasOperatorMemberAccessor和HasOperatorMemberAccessorOBJECT之间的唯一区别是HasOperatorMemberAccessorOBJECT的类型名称R硬编码到对象,
所以问题是"decltype(GetReturnType(&U :: operator->))"没有正确返回Object.我尝试了许多发现返回类型的不同许可.它们如下:
decltype( GetReturnType(&U::operator->) )
typename decltype( GetReturnType(&U::operator->))
decltype( ((U*)nullptr)->operator->() )
typename decltype( ((U*)nullptr)->operator->() )
Run Code Online (Sandbox Code Playgroud)
没有工作,为什么?我正在使用MSVC++ 10.0.
您是在问如何实现这样的特征,或者为什么decltype行为不符合您的预期?如果是前者,这是一种方法:
#include <type_traits>
template<typename T, bool DisableB = std::is_fundamental<T>::value>
struct HasOperatorMemberAccessor
{
private:
typedef char no;
struct yes { no m[2]; };
struct ambiguator { char* operator ->() { return nullptr; } };
struct combined : T, ambiguator { };
static combined* make();
template<typename U, U> struct check_impl;
template<typename U>
static no check(
U*,
check_impl<char* (ambiguator::*)(), &U::operator ->>* = nullptr
);
static yes check(...);
public:
static bool const value=std::is_same<decltype(check(make())), yes>::value;
};
// false for fundamental types, else the definition of combined will fail
template<typename T>
struct HasOperatorMemberAccessor<T, true> : std::false_type { };
// true for non-void pointers
template<typename T>
struct HasOperatorMemberAccessor<T*, false> :
std::integral_constant<
bool,
!std::is_same<typename std::remove_cv<T>::type, void>::value
>
{ };
template<typename X>
struct PointerX
{
X* operator ->() const { return nullptr; }
};
struct X { };
int main()
{
static_assert(
HasOperatorMemberAccessor<PointerX<bool>>::value,
"PointerX<> has operator->"
);
static_assert(
!HasOperatorMemberAccessor<X>::value,
"X has no operator->"
);
static_assert(
HasOperatorMemberAccessor<int*>::value,
"int* is dereferencable"
);
static_assert(
!HasOperatorMemberAccessor<int>::value,
"int is not dereferencable"
);
static_assert(
!HasOperatorMemberAccessor<void*>::value,
"void* is not dereferencable"
);
}
Run Code Online (Sandbox Code Playgroud)
VC++ 2010 缺乏必要的 C++11 工具(例如表达式 SFINAE)来使其更加简洁。