Vit*_*meo 7 c++ templates void template-meta-programming c++14
目前,我正在使用此方法来检查类是否具有特定签名的方法.
在参加了Walter E. Brown的元编程CppCon2014演讲之后,我开始想知道是否void_t
可以在这种特殊情况下使用它来使代码更清晰,更易读.
但是我在思考方面遇到了麻烦 void_t
- 到目前为止我理解这void_t
可以帮助我在编译时确定表达式是否有效.
例:
template< class, class = void >
struct has_type_data_member : false_type { };
template< class T >
struct has_type_data_member<T, void_t<decltype(T::data)>> : true_type { };
Run Code Online (Sandbox Code Playgroud)
如果decltype(T::type)
是有效表达式,则为has_type_data_member<T>
真正的编译时常量.因此,我们确信T
有一个成员字段data
.
我想使用相同的方法来检查类型T
是否具有具有特定名称和特定签名的方法.
假设我想检查是否T
有一个名为getCount()
return 的方法int
.这是我期望的工作((Ideone.com链接)):
template< class, class = void >
struct hasGetCount : false_type { };
template< class T >
struct hasGetCount<T, VoidT<decltype(T::getCount)>>
: std::is_same<decltype(std::declval<T>().getCount()), int>::type { };
Run Code Online (Sandbox Code Playgroud)
不幸的是,static_assert
测试没有通过.
我究竟做错了什么?void_t
在这种情况下可以使用吗?
奖金问题:
我可以使用宏来定义这样的辅助结构,如下所示:
DEFINE_METHOD_CHECKER(hasGetCount, getCount);
// ...
static_assert(hasGetCount<ClassWithGetCount>::value == true, "");
Run Code Online (Sandbox Code Playgroud)
是否可以避免必须先定义struct
第一个然后检查结构的值?我的意思是,是否可以使用宏来编写这样的东西?例:
static_assert(CHECK_METHOD(ClassWithGetCount, getCount)::value == true, "");
Run Code Online (Sandbox Code Playgroud)首先,命名非静态成员函数的id-expression不能用作未评估的操作数(例如操作数decltype
).此外,您应该检查整个函数调用表达式是否格式正确,而不仅仅是否有一个名为的成员getCount
:
template< class, class = void >
struct hasGetCount : false_type { };
template< class T >
struct hasGetCount<T, VoidT<decltype(std::declval<T>().getCount())>>
: std::is_same<decltype(std::declval<T>().getCount()), int>::type { };
Run Code Online (Sandbox Code Playgroud)
(declval<T&>
如果要检查是否getCount()
可以在左值上调用,请使用.)
如果您只是检查是否存在getCount
成员,那么如果具有该名称的成员存在但不可调用(例如,数据成员),则会出现硬错误.
虽然在这一点上你也可以考虑使用类似的东西
template< class T >
struct hasGetCount<T, std::enable_if_t<std::is_same<decltype(std::declval<T>().getCount()), int>::value>> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)
而不是写decltype
两次.
您可以使用void_t
以轻松验证返回类型getCount
是否可转换为int
:
template< class, class = void >
struct hasGetCount : false_type { };
template< class T >
struct hasGetCount<T,
VoidT<
decltype(std::declval<int&>() = std::declval<T>().getCount())
>> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
希望在C++ 17推出时,我们可以使用Concepts Lite更轻松地完成这项工作:
template <typename T>
concept bool hasGetCount = requires (T t) {
{ t.getCount() } -> int;
};
Run Code Online (Sandbox Code Playgroud)