Mona the Monad
Mona the Monad

Reputation: 2445

"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.

Upvotes: 8

Views: 3504

Answers (2)

Ivaylo Valchev
Ivaylo Valchev

Reputation: 10425

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.

Upvotes: 11

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29022

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");

Upvotes: 5

Related Questions