Detect transparent comparators
After writing about std::map::lower_bound
and transparent comparators, a question that followed up was "How to detect at compile time if the comparator is transparent or not?".
A comparator is transparent if it defines an is_transparent
type.
struct comparator0{
bool is_transparent;
// operator() and eventually others
};
struct comparator1{
using is_transparent = int;
// operator() and eventually others
};
struct comparator2{
using is_transparent = void;
// operator() and eventually others
};
Both comparator1
and comparator2
are transparent comparators, as long as the tag type is_transparent
is defined, thus something like using a = comparator1::is_transparent;
is valid. comparator0
is thus not a transparent comparator.
Looking back at how to detect member variables at compile time, it is possible to define a similar set of structures for querying if is_transparent
is defined or not.
But contrary to the approach used for member variables, we cannot use decltype
and void()
for specializing a template.
For types, we can use std::void_t
, which converts any type to… void
.
#include <type_traits>
#include <map>
template <typename T, typename = void>
struct is_transparent_comparator : std::false_type{};
template <typename T>
struct is_transparent_comparator<T, std::void_t<typename T::is_transparent>> : std::true_type {};
struct comparator0{
bool is_transparent;
// operator() and eventually others
};
struct comparator1{
using is_transparent = int;
// operator() and eventually others
};
struct comparator2{
using is_transparent = void;
// operator() and eventually others
};
struct incomplete;
struct comparator3{
using is_transparent = incomplete;
// operator() and eventually others
};
static_assert(not is_transparent_comparator<comparator0>::value);
static_assert( is_transparent_comparator<comparator1>::value);
static_assert( is_transparent_comparator<comparator2>::value);
static_assert( is_transparent_comparator<comparator3>::value);
static_assert( is_transparent_comparator<std::less<>>::value);
static_assert(not is_transparent_comparator<std::map<int,int>::key_compare>::value);
static_assert( is_transparent_comparator<std::map<int,int,std::less<>>::key_compare>::value);
Note that if you do not have access to C++17 yet, then template <class> struct my_void_t { using type = void; };
is a good enough replacement for std::void_t
.
Do you want to share your opinion? Or is there an error, some parts that are not clear enough?
You can contact me anytime.