和Sfinae有麻烦。我需要能够确定一个类型是否定义了成员函数运算符->,而不管它的返回类型如何。示例如下。
template <class X>
class PointerX
{
...
X* operator->() const;
...
}
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);
};
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);
};
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<>*)
}
HasOperatorMemberAccessor无法找到PointX的成员函数“Object Operator->()Const”。因此它使用Test的通用版本测试(...)。
但是,HasOperatorMemberAccessorOBJECT能够找到PointX的“Object Operator->()常量”。因此,它使用测试专用版本测试(SFINAE*)。
两者都应该能够找到“Object Operator->()Const”方法;因此两者都应该使用Test的专用版本测试(SFINAE*);因此HasOperatorMemberAccessor>::Value对两者都应为true。
decltype( GetReturnType(&U::operator->) )
typename decltype( GetReturnType(&U::operator->))
decltype( ((U*)nullptr)->operator->() )
typename decltype( ((U*)nullptr)->operator->() )
您是在问如何实现这样一个特征,或者为什么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"
);
}
VC++2010缺乏必要的C++11设施(例如表达式SFINAE),使其更加干净。
下一个;让我们调用模板化成员函数的不同实例: 最后是问题: Foo类的所有实例都来自同一个类?看来答案是肯定的但是...第一个Foo实例的末尾有f成员函数的两个重载:
这是怎么做到的? 示例:假设我有较高的kinded类型,其中有一个成员函数模板: 现在我想指定一个概念来约束这些更高级别的类型:
(沙盒) 获取此错误: 类型“number”不可分配给类型“T”“number”可分配给“T”类型的约束,但“T”可以用约束{}的不同子类型实例化。(2322)输入。ts(1,26):预期类型来自此签名的返回类型。 我希望typescript能够自动推断T为数字,然后直接使用它。为什么它在抱怨?写这样的东西的正确方法是什么?谢谢
我有这样的代码 现在,为了打印值,如果T是一个类,我想调用对象的打印函数,但是如果T是一个基本数据类型,我只想使用printf。 那么,如何确定模板类型是基本数据类型还是类?
OpenGL定义了C函数来管理资源。我编写了一个简单的包装器来以RAII的方式处理它们。函数对类似于和。但是,也有一些函数对适用于资源数组,例如和。对于前者,我编写了一个简单的类来完成这项工作,对于后者,我编写了另一个处理数组的类。然而,我注意到有时我只使用一个缓冲区或纹理,在那里我不必承担向量的费用,我想如果发布函数在开始时采用大小参数,我会专门化类析构函数,但是... 对于上述SSCCE g树
对于将SFINAE与可变模板类一起使用,我似乎找不到一个好的解决方案。 假设我有一个不喜欢引用的可变参数模板对象: 以及一个类,可以方便地检查参数包是否包含引用: 我如何使用它来专门化NoRef的情况下,引用存在于arg包?