Jes*_*Jes 7 c++ templates sfinae c++11
我了解到SFINAE可用于确定成员函数是否存在于类中.例如,以下代码可用于检查方法hello是否存在于类中.
struct has_method_hello {
using yes = char[1];
using no = char[2];
template <typename U, typename C>
static constexpr yes& test(decltype(&U::hello));
template <typename>
static constexpr no& test(...);
static constexpr bool value = (sizeof(yes) == sizeof(test<T>(nullptr)));
};
struct Foo {
void hello() {}
}
std::cout << has_method_hello <Foo> :: value << std::endl; // 1
Run Code Online (Sandbox Code Playgroud)
但是,假设hello是模板化的,我该如何修改技巧以使它仍能正常运行?
struct Foo {
template <typename T>
void hello(T&) {...}
}
Run Code Online (Sandbox Code Playgroud)
namespace details {
template<template<class...>class Z, class, class...>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:
std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply=details::can_apply<Z, void, Ts...>;
Run Code Online (Sandbox Code Playgroud)
现在你想知道是否foo.hello(int&)可以调用:
我们为hello_r您提供了调用的返回类型.hello:
template<class F, class...Ts>
using hello_r = decltype(std::declval<F>().hello( std::declval<Ts>()... ));
Run Code Online (Sandbox Code Playgroud)
这导致can_hello:
template<class F, class...Ts>
using can_hello = can_apply<hello_r, F, Ts...>;
Run Code Online (Sandbox Code Playgroud)
现在
struct Foo {
template <typename T>
void hello(T&) {...}
};
int main() {
std::cout << can_hello<Foo&, int&>::value << '\n';
std::cout << can_hello<Foo&, char&>::value << '\n';
std::cout << can_hello<Foo&>::value << '\n';
}
Run Code Online (Sandbox Code Playgroud)
打印 110。
首先,向您展示原始代码的缩短版本:
template <typename T>
struct has_method_hello {
static constexpr auto test(int) -> decltype(std::declval<T&>().hello(), std::true_type());
static constexpr std::false_type test(...);
using result_type = decltype(test(0));
static const bool value = result_type::value;
};
struct Foo {
void hello() {}
};
Run Code Online (Sandbox Code Playgroud)
现在使其适用于模板参数,很简单,一个示例:
template <typename T>
struct has_method_hello {
static constexpr auto test(int) -> decltype(std::declval<T&>().hello(std::declval<int&>()), std::true_type());
static constexpr std::false_type test(...);
using result_type = decltype(test(0));
static const bool value = result_type::value;
};
struct Foo {
template <typename T>
void hello(T& v) {}
};
Run Code Online (Sandbox Code Playgroud)
请注意,我int在这里有硬编码类型。您也可以制作模板的该部分has_method_hello。