jtb*_*des 9 c++ member-functions sfinae template-specialization c++11
我试图baz()在模板参数中检测成员函数的存在:
template<typename T, typename = void>
struct ImplementsBaz : public std::false_type { };
template<typename T>
struct ImplementsBaz<T, decltype(&T::baz)> : public std::true_type { };
Run Code Online (Sandbox Code Playgroud)
但它总是产生错误:
struct Foo {};
struct Bar { void baz() {} };
std::cout << ImplementsBaz<Foo>::value << std::endl; // 0
std::cout << ImplementsBaz<Bar>::value << std::endl; // also 0
Run Code Online (Sandbox Code Playgroud)
但是,使用declval和调用该方法确实有效:
template<typename T>
struct ImplementsBaz<T, decltype(std::declval<T>().baz())> : public std::true_type { };
Run Code Online (Sandbox Code Playgroud)
当然,现在这只能检测baz带有0个参数的函数.为什么在使用时正确选择了专业化declval<T>().baz(),但没有decltype(&T::baz)?
如果您使用void_t“检测习惯用法”,那么它确实按预期工作:
template <typename...> using void_t = void;
template <typename T>
struct ImplementsBaz<T, void_t<decltype(&T::baz)>> : std::true_type {};
struct Bar { void baz() {} };
static_assert(ImplementsBaz<Bar>::value); // passes
Run Code Online (Sandbox Code Playgroud)
至于为什么,这个问题详细解释了“void_t技巧”是如何工作的。引用已接受的答案:
就好像你写过一样
has_member<A, void>::value。现在,将模板参数列表与模板的任何特化进行比较has_member。仅当没有专业化匹配时,主模板的定义才用作后备。
在原始情况下,decltype(&T::baz)is not void,因此特化与原始模板不匹配,因此不考虑。我们需要使用void_t(或某种其他机制,例如强制转换)将类型更改为,void以便使用特化。
| 归档时间: |
|
| 查看次数: |
1149 次 |
| 最近记录: |