Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Conditional" alias templates

In a type like the unspecialized template struct pointer_traits (i.e. template <class Ptr> struct pointer_traits), there exists a member alias template rebind that is defined to be Ptr::rebind<U>, if it exists, or some other type otherwise. Though I have seen a few answers on checking whether a certain member exists, how does one implement a "conditional" alias template like pointer_traits::rebind? That is, as if by the following pseudo-C++:

template <typename T> using type = has_type<T::U> ? int : float;

or

template <typename T> using type = if_has_type<T::U, int, float>::type;

I considered using something like the method depicted at https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector (section "Detecting member types"), but I don't know how to implement a helper struct whose [sole] member type depends on the existence of another member type.

like image 420
Mona the Monad Avatar asked Dec 24 '22 21:12

Mona the Monad


2 Answers

By using std::conditional from <type_traits>. It's as simple as:

using type = typename std::conditional<bool, int, float>::type;

or

using type = std::conditional_t<bool, int, float>;

where you replace bool with some condition, evaluable at compile-time to a boolean value. In this case the condition is the check for an existing member.

If the condition is true type becomes an alias to int, otherwise to float.

FULL EXAMPLE (Check if difference_type is a member type.)

namespace detail {

template<class Ptr>
using ptrait_diff = typename Ptr::difference_type;

template<class Ptr, bool = is_detected<ptrait_diff, Ptr>::value>
struct ptrait_diff_t { 
    using type = ptrdiff_t;
};

template<class Ptr>
struct ptrait_diff_t<Ptr, true> {
    using type = typename Ptr::difference_type;
};

} // namespace detail

and then:

template<class Ptr>
struct pointer_traits
{
    using difference_type = typename detail::ptrait_diff_t<Ptr>::type;
};

Implementation of is_detected can be found HERE.

like image 50
DeiDei Avatar answered Jan 10 '23 18:01

DeiDei


This is the problem std::conditional is designed to solve.

#include <type_traits>
template<bool condition> 
using type = std::conditional_t<condition, int, float>;

static_assert(std::is_same<type<true>,  int>::value,   "type<true> should be int");
static_assert(std::is_same<type<false>, float>::value, "type<false> should be float");
like image 23
François Andrieux Avatar answered Jan 10 '23 16:01

François Andrieux