"Conditional" 别名模板

"Conditional" alias templates

在像非专用模板结构 pointer_traits(即 template <class Ptr> struct pointer_traits)这样的类型中,存在一个定义为 Ptr::rebind<U> 的成员别名模板 rebind,如果它存在,或者其他一些类型。虽然我已经看到一些关于 检查 某个成员是否存在的答案,但是如何实现像 pointer_traits::rebind 这样的 "conditional" 别名模板?也就是说,就好像通过以下伪 C++:

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

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

我考虑过使用类似于 https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector(第 "Detecting member types" 节)中描述的方法,但我不知道如何实现其 [唯一] 成员类型取决于存在的辅助结构另一种成员类型。

通过使用 <type_traits> 中的 std::conditional。就这么简单:

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

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

bool 替换为某些条件,可在 compile-time 处评估为布尔值。在这种情况下,条件是检查现有成员。

如果条件为 true,则类型成为 int 的别名,否则为 float

完整示例(检查 difference_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

然后:

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

可以找到 is_detected 的实现 HERE

这就是std::conditional旨在解决的问题。

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