Namespaces | Classes | Typedefs | Variables

Simple traits for the implementation of other traits. More...

Namespaces

 util::details
 

Classes

struct  util::self_type< T >
 Trait returning the very same type as in the template argument. More...
 
struct  util::always_false_type< typename >
 A std::false_type with a template argument. More...
 
struct  util::always_true_type< typename >
 A std::true_type with a template argument. More...
 
struct  util::find_next_type< T, StartFrom, Types >
 Trait: index of the first occurrence of T among the specified Types, starting from the one with index StartFrom. More...
 
struct  util::is_any_of< T, Types >
 Trait: whether T is among the specified Types. More...
 

Typedefs

template<typename T >
using util::self_t = typename self_type< T >::type
 The very same type as in the template argument. More...
 
using util::type_traits = std::bool_constant< Value >
 
template<typename A , typename B >
using util::is_not_same = std::negation< std::is_same< A, B >>
 The negation of std::is_same. More...
 
template<typename T , typename... Types>
using util::find_type = find_next_type< T, 0U, Types... >
 Trait: index of the first occurrence of T among the specified Types. More...
 

Variables

template<typename >
constexpr bool util::always_false_v = false
 A templated constant, always false. More...
 
template<typename >
constexpr bool util::always_true_v = true
 A template constant always true. More...
 
template<typename T , std::size_t StartFrom, typename... Types>
constexpr std::size_t util::find_next_type_v = find_next_type<T, StartFrom, Types...>::value
 
template<typename T , typename... Types>
constexpr std::size_t util::find_type_v = find_type<T, Types...>::value
 
template<typename T , typename... Types>
constexpr bool util::is_any_of_v = is_any_of<T, Types...>::value
 Whether T is among the specified Types (see util::is_any_of). More...
 
template<typename T , typename U >
constexpr auto util::is_same_decay_v = std::is_same_v<std::decay_t<T>, std::decay_t<U>>
 Whether T and U are the same type, after being applied std::decay. More...
 
template<typename T >
void util::staticDumpClassName ()
 Helper to determine the type of a variable at compilation time. More...
 
template<typename T >
void util::staticDumpClassName (T)
 
template<typename Target , typename... T>
using util::count_type_in_list = details::count_type_in_list_impl< Target, T... >
 Returns how many of the types in T exactly match Target. More...
 
template<std::size_t N, typename... T>
using util::typelist_element_type = std::tuple_element< N, std::tuple< T... >>
 Returns the N type of the type list. More...
 
template<std::size_t N, typename... T>
using util::typelist_element_t = typename typelist_element_type< N, T... >::type
 Direct access to the value in typelist_element_type. More...
 
template<typename Target , typename... T>
using util::type_is_in = details::type_is_in_impl< Target, T... >
 Holds whether the Target type is among the ones in the T pack. More...
 
template<typename Target , typename... T>
constexpr unsigned int util::count_type_in_list_v = count_type_in_list<Target, T...>()
 Direct access to the value in count_type_in_list. More...
 
template<typename Target , typename... T>
constexpr bool util::type_is_in_v = type_is_in<Target, T...>()
 Direct access to the value in type_is_in. More...
 

Detailed Description

Simple traits for the implementation of other traits.

Class triggering a static_assert failure.

Template Parameters
Ttype accompanying the assertion
Enableassertion will fail only if Enable expands to true

Instantiating this class anywhere (where it's legit) will trigger a static assertion failure. Since the error message emitted by the compiler usually contains an expansion of the template parameters, it is then possible to see the "value" of type T that was used when the assertion failed. The argument Enable allows to tune when the assertion should fail.

For the following example, we want to investigate the value of the type element_type, which is provided, among others, by std::unique_ptr. We want to find out the exact type element_type of the collection type passed to OurClass, but only when the collection type is, say, not constant:

template <typename Coll>
struct OurClass {
using Collection_t = Coll;
using value_type = typename Collection_t::element_type;
// DEBUG: have the compiler print `value_type`
<value_type, std::is_const_v<std::remove_reference_t<Coll>>>
debugVar;
}; // struct OurClass
// this should never trigger a static assertion failure:
// this triggers a static assertion failure:

(a working example is provided in DebugUtils_test.h). The output with GCC 7.2 is similar to the following: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from larcorealg/test/CoreUtils/DebugUtils_test.cc:17:0: larcorealg/larcorealg/CoreUtils/DebugUtils.h: In instantiation of ‘struct lar::debug::details::THE_TYPE_IS<int [10]>’: larcorealg/larcorealg/CoreUtils/DebugUtils.h:476:29: required from ‘struct lar::debug::static_assert_on<int [10], true>’ larcorealg/test/CoreUtils/DebugUtils_test.cc:49:5: required from ‘struct OurClass<const std::unique_ptr<int [10]> >’ larcorealg/test/CoreUtils/DebugUtils_test.cc:61:51: required from here larcorealg/larcorealg/CoreUtils/DebugUtils.h:467:7: error: static assertion failed: static_assert_on<T>: check the error message ("THE_TYPE_IS<>") for expansion of type T. static_assert(util::always_false_v<T>, ^~~~~~~~~~~~~

The message of the assertion points to the key string ("THE_TYPE_IS"), and
it can be seen in the second line of this excerpt that the information is
printed as `struct lar::debug::details::THE_TYPE_IS<int [10]>`.
This is Clang 5.0:

In file included from larcorealg/test/CoreUtils/DebugUtils_test.cc:17: larcorealg/larcorealg/CoreUtils/DebugUtils.h:451:7: error: static_assert failed "static_assert_on<T>: check the error message (\"THE_TYPE_IS<>") for expansion of type `T`." static_assert(util::always_false_v<T>, ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ larcorealg/larcorealg/CoreUtils/DebugUtils.h:460:29: note: in instantiation of template class 'lar::debug::details::THE_TYPE_IS<int [10]>' requested here details::THE_TYPE_IS<T> _; ^ larcorealg/test/CoreUtils/DebugUtils_test.cc:49:5: note: in instantiation of template class 'lar::debug::static_assert_on<int [10], true>' requested here debugVar; ^ larcorealg/test/CoreUtils/DebugUtils_test.cc:61:10: note: in instantiation of template class 'OurClass<const std::__1::unique_ptr<int [10], std::__1::default_delete<int [10]> > >' requested here (void) OurClass<std::unique_ptr<int[10]> const>(); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ where the type can be read in the message of the first note.

Typedef Documentation

template<typename Target , typename... T>
using util::count_type_in_list = typedef details::count_type_in_list_impl<Target, T...>

Returns how many of the types in T exactly match Target.

Definition at line 107 of file TupleLookupByTag.h.

template<typename T , typename... Types>
using util::find_type = typedef find_next_type<T, 0U, Types...>

Trait: index of the first occurrence of T among the specified Types.

Template Parameters
Tthe type of check the presence of
Typesthe possible types T can match.
See also
util::find_next_type

The value of the trait is the index of T within the specified list of Types (first type as index 0). The match is exact, as in std::is_same. If none of the Types exactly matches T, the trait value will be the number of types (i.e. sizeof...(Types)), which is the index after the last of the types.

This is a integral trait (type std::size_t): use it as std::integer_constant.

Definition at line 232 of file MetaUtils.h.

template<typename A , typename B >
using util::is_not_same = typedef std::negation<std::is_same<A, B>>

The negation of std::is_same.

Definition at line 183 of file MetaUtils.h.

template<typename T >
using util::self_t = typedef typename self_type<T>::type

The very same type as in the template argument.

Definition at line 68 of file MetaUtils.h.

template<typename Target , typename... T>
using util::type_is_in = typedef details::type_is_in_impl<Target, T...>

Holds whether the Target type is among the ones in the T pack.

Definition at line 125 of file TupleLookupByTag.h.

typedef std::negation< BoolTrait > util::type_traits

Definition at line 174 of file MetaUtils.h.

template<std::size_t N, typename... T>
using util::typelist_element_t = typedef typename typelist_element_type<N, T...>::type

Direct access to the value in typelist_element_type.

Definition at line 120 of file TupleLookupByTag.h.

template<std::size_t N, typename... T>
using util::typelist_element_type = typedef std::tuple_element<N, std::tuple<T...>>

Returns the N type of the type list.

Definition at line 116 of file TupleLookupByTag.h.

Function Documentation

template<typename T >
void util::staticDumpClassName ( )

Helper to determine the type of a variable at compilation time.

Template Parameters
Ttype to be investigated

It may be difficult to understand which type is being used in a failing static assertion or in some complicate metaprogramming code (is there any other kind?), especially when due to a compilation failure the code can't be run. This class is supposed to help by forcing the compiler to a halt, and it is devised so that the compiler should print in the error message what it thinks the type T is.

An example of usage:

void f() {
constexpr auto v = 5U - 6U; // which type is `v` of?
}

For example, Clang 5.0.1 emits these errors:

In file included from metatest.cpp:1:
./MetaUtils.h:217:7: error: static_assert failed "ClassNameStaticDumper<T>: look for T in the error message context"
static_assert(
^
./MetaUtils.h:228:39: note: in instantiation of template class 'util::details::ClassNameStaticDumper<unsigned int>' requested here
void staticDumpClassName() { (void) details::ClassNameStaticDumper<T>(); }
^
./MetaUtils.h:195:46: note: in instantiation of function template specialization 'util::staticDumpClassName<unsigned int>' requested here
[[noreturn]] void staticDumpClassName(T) { staticDumpClassName<T>(); }
^
metatest.cpp:5:16: note: in instantiation of function template specialization 'util::staticDumpClassName<unsigned int>' requested here
^
1 error generated.

From the first "note" we can see that the type of v is unsigned int. Note that if v is not copiable, an additional error will be emitted. To avoid that, the type can be specified as template parameter, as in util::staticDumpClassName<decltype(v)>(). The same program is processed by GNU GCC with an error message: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from metatest.cpp:1:0: MetaUtils.h: In instantiation of ‘struct util::details::ClassNameStaticDumper<unsigned int>’: MetaUtils.h:248:48: required from ‘void util::staticDumpClassName() [with T = unsigned int]’ MetaUtils.h:215:68: required from ‘void util::staticDumpClassName(T) [with T = unsigned int]’ metatest.cpp:5:30: required from here MetaUtils.h:237:7: error: static assertion failed: ClassNameStaticDumper<T>: look for T in the error message context static_assert( ^~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ where the type is mentioned in all the three context lines.

Definition at line 986 of file MetaUtils.h.

986 { (void) details::ClassNameStaticDumper<T>(); }
template<typename T >
void util::staticDumpClassName ( )

Definition at line 327 of file MetaUtils.h.

327 { staticDumpClassName<T>(); }

Variable Documentation

template<typename >
constexpr bool util::always_false_v = false

A templated constant, always false.

See also
util::always_false_type, util::always_true_v

This constant allows a static_assert to fail only when the template type it's in is being instantiated:

template <typename T>
struct MandatoryCustomizationPoint {
static_assert(util::always_false_v<T>, "You have to specialize!");
};
template <typename T>
struct MandatoryCustomizationPoint<std::vector<T>> {
using type = typename std::vector<T>::reference;
};

In this example, using std::false_type might have tipped the compiler to trigger the assertion failure even if the class is not instantiated.

Definition at line 119 of file MetaUtils.h.

template<typename >
constexpr bool util::always_true_v = true

A template constant always true.

See also
util::always_true_type, util::always_false_v

This is one way to allow to specialize for classes with a certain type:

template <typename T, typename = void>
class ReferenceTypeExtractor {
static_assert(util::always_false_v<T>, "Type has no reference!");
};
template <typename Cont>
struct ReferenceTypeExtractor
<Cont, std::enable_if_t<util::always_true_v<typename Cont::value_type>>>
{
using type = typename Cont::reference;
};

Definition at line 168 of file MetaUtils.h.

template<typename Target , typename... T>
constexpr unsigned int util::count_type_in_list_v = count_type_in_list<Target, T...>()

Direct access to the value in count_type_in_list.

Definition at line 112 of file TupleLookupByTag.h.

template<typename T , std::size_t StartFrom, typename... Types>
constexpr std::size_t util::find_next_type_v = find_next_type<T, StartFrom, Types...>::value

Definition at line 211 of file MetaUtils.h.

template<typename T , typename... Types>
constexpr std::size_t util::find_type_v = find_type<T, Types...>::value

Index of the first occurrence of T among the specified Types.

See also
util::find_type

Definition at line 238 of file MetaUtils.h.

template<typename T , typename... Types>
constexpr bool util::is_any_of_v = is_any_of<T, Types...>::value

Whether T is among the specified Types (see util::is_any_of).

Definition at line 256 of file MetaUtils.h.

template<typename T , typename U >
constexpr auto util::is_same_decay_v = std::is_same_v<std::decay_t<T>, std::decay_t<U>>

Whether T and U are the same type, after being applied std::decay.

Definition at line 263 of file MetaUtils.h.

template<typename Target , typename... T>
constexpr bool util::type_is_in_v = type_is_in<Target, T...>()

Direct access to the value in type_is_in.

Definition at line 129 of file TupleLookupByTag.h.