关于c ++:“条件”别名模板

“Conditional” alias templates

在非专用模板结构pointer_traits这样的类型(即template struct pointer_traits中),存在一个成员别名模板rebind,如果存在,则定义为Ptr::rebind或其他类型。虽然我看到了一些关于检查某个成员是否存在的答案,但是如何实现像pointer_traits::rebind这样的"条件"别名模板?也就是说,就像下面的伪C++:

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

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

我曾考虑过使用类似于https://en.wikibooks.org/wiki/more_c%2b%2b_惯用法/成员_检测器(检测成员类型一节)中描述的方法,但我不知道如何实现一个助手结构,其[唯一]成员类型取决于另一个成员类型的存在。


中使用std::conditional。它很简单:

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

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

在使用某些条件替换bool时,可以在编译时计算为布尔值。在这种情况下,条件是检查现有成员。

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

完整示例(检查difference_type是否为成员类型。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

然后:

1
2
3
4
5
template<class Ptr>
struct pointer_traits
{
    using difference_type = typename detail::ptrait_diff_t<Ptr>::type;
};

这里可以找到is_detected的实现。


这就是std::conditional设计用来解决的问题。

1
2
3
4
5
6
#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");