5

Sorry for asking so simple question, but I cannot find the answer easily. Google says nothing interesting about "C++ negation integral_constant" and similar queries.

Is there in C++11 any trait that make std::true_type from std::false_type and vice versa? In other words, I'd like some more readeble version of

std::is_same<my_static_bool, std::false_type>

I know of course I can write it myself, but I'd like to use the existing one if there is such.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
peper0
  • 3,111
  • 23
  • 35
  • What is the problem with doing `!my_static_bool`? – David Rodríguez - dribeas Feb 06 '13 at 20:07
  • @DavidRodríguez-dribeas: I think `my_static_bool` is an integral constant, so he would have to write `std::integral_constant` (intentionally without `::value`) to make it right. – ipc Feb 06 '13 at 20:08
  • @ipc `constexpr` `operator!` might make it possible, haven't tried though. – Maxim Egorushkin Feb 06 '13 at 20:12
  • @MaximYegorushkin: You can't apply operators on types. – ipc Feb 06 '13 at 20:13
  • @ipc: From the test above, it seems that `my_static_bool` can be `std::false_type` (or possibly `std::true_type` I imagine). Other than that, I don't quite understand your comment... `std::integral_constant` has a `constexpr` conversion operator `operator value_type()` that in the case of `std::false_type` yields `false`, which can be used with the *not* to yield a `true` constant expression – David Rodríguez - dribeas Feb 06 '13 at 20:14
  • @DavidRodríguez-dribeas: You can't write `!std::true_type`. – ipc Feb 06 '13 at 20:15
  • @ipc: Right... my bad, you can only apply the operator to an object, not to the type :) The alternatives are either `!my_static_bool::value` or `!my_static_bool{}` – David Rodríguez - dribeas Feb 06 '13 at 20:17

4 Answers4

7

There is not, because it's essentially a one-liner and the <type_traits> should be as small as possible.

template <typename T> using static_not = std::integral_constant<bool, !T::value>;

Usage:

static_not<my_static_bool>

This is the correct way because the standard always says "false_type or derived from such", so you can't depend on being equal to std::false_type. I usually relax that to "having a constexpr boolean ::value property" because I don't use tag dispatching.

ipc
  • 8,045
  • 29
  • 33
4

Yet another way to do it:

template <typename T>
using static_not = typename std::conditional<
    T::value,
    std::false_type,
    std::true_type
>::type;
Tavian Barnes
  • 12,477
  • 4
  • 45
  • 118
aschepler
  • 70,891
  • 9
  • 107
  • 161
2

The following code uses template metafunction forwarding (i.e. it inherits from std::integral_constant with a negated boolean value, this is of course inspired by the Boost.MPL that heavily uses this pattern)

#include <type_traits>

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

int main()
{
   typedef logical_not<std::false_type>::type T;
   typedef logical_not<std::true_type>::type F;

   static_assert((std::is_same<T, std::true_type>::value), "");
   static_assert((std::is_same<F, std::false_type>::value), "");   
}

Output on LiveWorkSpace

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
1

The types true_type and false_type have a nested typedef that refers to themselves, so you can write:

std::is_same<my_static_bool::type,std::false_type>::value

Depending on the context it might be simpler to just do !my_static_bool{}, which is a constexpr of value true if your type is indeed std::false_type.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489