Reputation: 13512
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
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
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
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