1

I need a trait which will check if a given type has an inner template named rebind which takes a single template type parameter. Something like:

template <typename X>
struct has_rebind
{
    static const bool value = /* ??? */;
};

This is similar to what BOOST_TTI_HAS_TEMPLATE does, but I want to implement the trait without the use of Boost TTI, and I do not know how that macro is implemented.

Barry
  • 286,269
  • 29
  • 621
  • 977
eupp
  • 535
  • 3
  • 13

1 Answers1

4

C++11 and up gives us a wealth of alternatives with which to write arbitrarily complex type traits in fairly simple fashion. One such is void_t:

template <typename... >
using void_t = void;

All you do is write a base trait:

template <typename X, typename = void>
struct has_rebind : std::false_type { };

and then a partial specialization that will only pass template deduction if the criteria you want is met, namely that X has a rebind<T>. In this case, the type doesn't matter, so we can just pick one:

template <typename X>
struct has_rebind<X, void_t<typename X::template rebind<int>>>
: std::true_type { };

Demo


A different approach to the same thing is Yakk's can_apply, which with some boilerplate:

namespace details {
  template<class...>struct voider{using type=void;};
  template<class...Ts>using void_t=typename voider<Ts...>::type;

  template<template<class...>class Z, class, class...Ts>
  struct can_apply:std::false_type{};
  template<template<class...>class Z, class...Ts>
  struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply=details::can_apply<Z,void,Ts...>;

We can write something similar:

template <typename X, typename T>
using rebind_t = typename X::template rebind<T>;

template <typename X>
using has_rebind = can_apply<rebind_t, X, int>;

Demo 2

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977