KnowItAllWannabe
KnowItAllWannabe

Reputation: 13512

How negate std::is_integral for use in tag dispatch?

I've been playing around with tag dispatch, and the following code works exactly as I expect:

#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)
}

But if I want to negate the condition, I'm running into trouble. I thought I could just throw a "!" into the code inside dispatch,

impl(!std::is_integral<T>());    // added "!"

but this won't compile.

What do I need to do to get this code to work?

Upvotes: 2

Views: 956

Answers (4)

Giovanni Cerretani
Giovanni Cerretani

Reputation: 1724

std::negation has been introduced in C++17.

Upvotes: 0

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275740

std::false_type negate( std::true_type ) { return {}; }
std::true_type negate( std::false_type ) { return {}; }
impl(negate(std::is_integral<T>()));

Or, a bit fancier:

template<typename T, T x>
std::integral_constant<T, !x> negate( std::integral_constant<T,x> ) { return {}; }
impl(negate(std::is_integral<T>()));

which extends negate to work on all integral_constants.

Upvotes: 1

Casey
Casey

Reputation: 42574

You could implement operator ! for std::integral_constant (the underlying type for true_type and false_type):

template <typename T, T value>
inline constexpr std::integral_constant<T, !value>
operator ! (std::integral_constant<T, value>)
{ return {}; }

This seems like one of those handy little things that could easily be standardized.

Upvotes: 6

zaufi
zaufi

Reputation: 7129

you may instantiate a std::integral_constant from a constexpr value like this:

 impl(std::integral_constant<bool, !std::is_integral<T>::value>());

std::true_type and std::false_type actually aliases to this class. The other way is to introduce a metafunction for this:

template <typename T>
struct not_ : std::integral_constant<bool, !T::value> {};

and use (call) it:

impl(typename not_<std::is_integral<T>>::type());

or use the similar from boost::mpl

Upvotes: 5

Related Questions