每当表达式未定义时,在 C++ 中启用函数模板
Enable a function template in C++ whenever an expression is undefined
只要某些表达式被 un 定义(例如,类型 t
的 x
是 not 可流式传输到 std::cout
)。像
template<typename t>
auto f(const t &x)
-> typename enable_if_undefined<decltype(std::cout << x)>::type;
使用 SFINAE,我只知道如果定义了表达式如何启用,但不知道如果表达式未定义如何启用。
您需要一个助手来提供一个可以反转的布尔值:
template<typename, typename=void>
struct has_cout
: std::false_type {};
template<typename T>
struct has_cout<T, decltype(std::cout << std::declval<T>(),void())>
: std::true_type {};
template<typename T>
auto f(const T& x)
-> typename std::enable_if<!has_cout<T>::value>::type;
template<class...>struct types{using type=types;};
namespace details {
template<template<class...>class Z, class types, class=void>
struct test_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct test_apply<Z,types<Ts...>,std::void_t<Z<Ts...>>>:
std::true_type
{};
};
template<template<class...>class Z, class...Ts>
using test_apply=details::test_apply<Z,types<Ts...>>;
是元编程样板文件。
那么实际的用例特定代码真的很干净。首先,一个简单的 decltype
别名:
template<class X>
using cout_result = decltype( std::cout << std::declval<X>() );
然后我们对其进行测试:
template<class X>
using can_cout_stream = test_apply< cout_result, X >;
这里的目标是将元编程样板文件与实际使用分离。
template<class T>
std::enable_if_t<!can_cout_stream<const T&>{}>
f(const T& x)
我自由地使用 C++14 特性来使事情变得更干净。如果您的编译器没有它们,它们都可以在 C++11 中轻松(重新)实现。
template<bool b, class T=void>
using enable_if_t=typename std::enable_if<b,T>::type;
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
应该覆盖它。
只要某些表达式被 un 定义(例如,类型 t
的 x
是 not 可流式传输到 std::cout
)。像
template<typename t>
auto f(const t &x)
-> typename enable_if_undefined<decltype(std::cout << x)>::type;
使用 SFINAE,我只知道如果定义了表达式如何启用,但不知道如果表达式未定义如何启用。
您需要一个助手来提供一个可以反转的布尔值:
template<typename, typename=void>
struct has_cout
: std::false_type {};
template<typename T>
struct has_cout<T, decltype(std::cout << std::declval<T>(),void())>
: std::true_type {};
template<typename T>
auto f(const T& x)
-> typename std::enable_if<!has_cout<T>::value>::type;
template<class...>struct types{using type=types;};
namespace details {
template<template<class...>class Z, class types, class=void>
struct test_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct test_apply<Z,types<Ts...>,std::void_t<Z<Ts...>>>:
std::true_type
{};
};
template<template<class...>class Z, class...Ts>
using test_apply=details::test_apply<Z,types<Ts...>>;
是元编程样板文件。
那么实际的用例特定代码真的很干净。首先,一个简单的 decltype
别名:
template<class X>
using cout_result = decltype( std::cout << std::declval<X>() );
然后我们对其进行测试:
template<class X>
using can_cout_stream = test_apply< cout_result, X >;
这里的目标是将元编程样板文件与实际使用分离。
template<class T>
std::enable_if_t<!can_cout_stream<const T&>{}>
f(const T& x)
我自由地使用 C++14 特性来使事情变得更干净。如果您的编译器没有它们,它们都可以在 C++11 中轻松(重新)实现。
template<bool b, class T=void>
using enable_if_t=typename std::enable_if<b,T>::type;
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
应该覆盖它。