检查 SFINAE 是否存在类型声明
Checking whether a type declaration is present for SFINAE
我想使用 SFINAE 根据模板参数是否声明类型来重载函数模板 T
。到目前为止,这是我能够到达的地方:
struct C1 {
using T = int;
};
struct C2 {
using T = void; // but I would really like
// to not require T at all
};
// For classes that declare T
template <class C>
void f(C &c, typename std::enable_if<!std::is_same<typename C::T, void>::value,
int>::type = 0) {
(void)c;
std::cout << "With T" << std::endl;
}
// For classes that do not declare T (for now, T must be declared void)
template <class C>
void f(C &c, typename std::enable_if<std::is_same<typename C::T, void>::value,
int>::type = 0) {
(void)c;
std::cout << "Without T" << std::endl;
}
int main() {
C2 c;
f(c);
return 0;
}
如何(如果有的话)以 C2
根本不需要声明 T
的方式更改此解决方案? IE。我想要两个重载:一个用于声明 T
的 类,一个用于声明 T
的 类,一个不声明
。
#include <type_traits>
template <typename...>
struct voider { using type = void; };
template <typename... Ts>
using void_t = typename voider<Ts...>::type;
template <typename C, typename = void_t<>>
struct has_t : std::false_type {};
template <typename C>
struct has_t<C, void_t<typename C::T>> : std::true_type {};
template <typename C>
auto f(C& c)
-> typename std::enable_if<has_t<C>::value>::type
{
}
template <typename C>
auto f(C& c)
-> typename std::enable_if<!has_t<C>::value>::type
{
}
您可以根据需要创建类型特征:
template<typename Type, typename Enable=void>
struct has_t : std::false_type {};
template<typename Type>
struct has_t<Type, void_t<Type::T>> : std::true_type {};
void_t
实现如下:
template<typename...>
struct voider {
using type = void;
};
template<class... Ts> using void_t = typename voider<Ts...>::type;
此 void_t
实现保证在 C++11 中工作。
现在你可以像这样使用这个类型特征:
template<typename C, typename std::enable_if<has_t<typename std::decay<C>::type>::value, int>::type = 0>
void f(C&& c) {
// ... C::T exists
}
template<typename C, typename std::enable_if<!has_t<typename std::decay<C>::type>::value, int>::type = 0>
void f(C&& c) {
// ... C::T doesn't exists
}
您需要衰减类型,因为它将成为参考。由于 C
里面的 typedef 不在里面,比方说 C&
,你必须先删除引用。
我想使用 SFINAE 根据模板参数是否声明类型来重载函数模板 T
。到目前为止,这是我能够到达的地方:
struct C1 {
using T = int;
};
struct C2 {
using T = void; // but I would really like
// to not require T at all
};
// For classes that declare T
template <class C>
void f(C &c, typename std::enable_if<!std::is_same<typename C::T, void>::value,
int>::type = 0) {
(void)c;
std::cout << "With T" << std::endl;
}
// For classes that do not declare T (for now, T must be declared void)
template <class C>
void f(C &c, typename std::enable_if<std::is_same<typename C::T, void>::value,
int>::type = 0) {
(void)c;
std::cout << "Without T" << std::endl;
}
int main() {
C2 c;
f(c);
return 0;
}
如何(如果有的话)以 C2
根本不需要声明 T
的方式更改此解决方案? IE。我想要两个重载:一个用于声明 T
的 类,一个用于声明 T
的 类,一个不声明
#include <type_traits>
template <typename...>
struct voider { using type = void; };
template <typename... Ts>
using void_t = typename voider<Ts...>::type;
template <typename C, typename = void_t<>>
struct has_t : std::false_type {};
template <typename C>
struct has_t<C, void_t<typename C::T>> : std::true_type {};
template <typename C>
auto f(C& c)
-> typename std::enable_if<has_t<C>::value>::type
{
}
template <typename C>
auto f(C& c)
-> typename std::enable_if<!has_t<C>::value>::type
{
}
您可以根据需要创建类型特征:
template<typename Type, typename Enable=void>
struct has_t : std::false_type {};
template<typename Type>
struct has_t<Type, void_t<Type::T>> : std::true_type {};
void_t
实现如下:
template<typename...>
struct voider {
using type = void;
};
template<class... Ts> using void_t = typename voider<Ts...>::type;
此 void_t
实现保证在 C++11 中工作。
现在你可以像这样使用这个类型特征:
template<typename C, typename std::enable_if<has_t<typename std::decay<C>::type>::value, int>::type = 0>
void f(C&& c) {
// ... C::T exists
}
template<typename C, typename std::enable_if<!has_t<typename std::decay<C>::type>::value, int>::type = 0>
void f(C&& c) {
// ... C::T doesn't exists
}
您需要衰减类型,因为它将成为参考。由于 C
里面的 typedef 不在里面,比方说 C&
,你必须先删除引用。