我一直在玩标签调度,以下代码完全符合我的预期:
#include <type_traits>
#include <iostream>
void impl(std::true_type) { std::cout << "true\n"; }
void impl(std::false_type) { std::cout << "false\n"; }
template<typename T>
void dispatch(T&& val)
{
impl(std::is_integral<typename std::remove_reference<T>::type>());
}
int main()
{
dispatch(10); // calls impl(std::true_type)
dispatch(""); // calls impl(std::false_type)
}
但如果我想否定这种情况,我就会遇到麻烦。我以为我可以在!
,
dispatch
”
impl(!std::is_integral<T>()); // added "!"
但这不会编译。
要使此代码有效,我需要做什么?
答案 0 :(得分:5)
您可以从constexpr值中实例化std::integral_constant
,如下所示:
impl(std::integral_constant<bool, !std::is_integral<T>::value>());
std::true_type
和std::false_type
实际上是此类的别名。另一种方法是为此引入metafunction:
template <typename T>
struct not_ : std::integral_constant<bool, !T::value> {};
并使用(调用)它:
impl(typename not_<std::is_integral<T>>::type());
或使用boost::mpl
答案 1 :(得分:5)
您可以为operator !
(std::integral_constant
和true_type
的基础类型)实施false_type
:
template <typename T, T value>
inline constexpr std::integral_constant<T, !value>
operator ! (std::integral_constant<T, value>)
{ return {}; }
这似乎是那些易于标准化的便捷小事之一。
答案 2 :(得分:1)
std::false_type negate( std::true_type ) { return {}; }
std::true_type negate( std::false_type ) { return {}; }
impl(negate(std::is_integral<T>()));
或者,有点发烧友:
template<typename T, T x>
std::integral_constant<T, !x> negate( std::integral_constant<T,x> ) { return {}; }
impl(negate(std::is_integral<T>()));
扩展negate
以适用于所有integral_constants
。
答案 3 :(得分:0)
std::negation
已在 C++17 中引入。