std :: conditional如何工作

时间:2017-06-14 17:18:05

标签: c++ c++11 templates template-meta-programming template-specialization

我们将这个名为std::conditional的小编程奇迹描述为here。在同一参考文献中,它表示可能的实现是

template<bool B, class T, class F>
struct conditional { typedef T type; };

template<class T, class F>
struct conditional<false, T, F> { typedef F type; };

因此,如果在代码中我执行类似

的操作
typename std::conditional<true,int,double>::type a;

编译器将遵循第一个定义,如果我执行类似

的操作
typename std::conditional<false,int,double>::type b

编译器将采取第二个。为什么这样做?这里有什么编译规则?

3 个答案:

答案 0 :(得分:7)

简而言之,它与模板专业化规则有关。这些类似于函数重载,但对于类型。

这里编译器更喜欢更通用的类型。

template<bool B, class T, class F>
struct conditional { typedef T type; };

template<class T, class F>
struct conditional<false, T, F> { typedef F type; };

因此,如果编译器看到模板实例化coditional<false, ...>,它会找到:

  • 一般模板template<bool B, class T, class F> struct conditional
  • 所有专长:template<class T, class F> struct conditional<false, T, F>

此时它会尝试匹配尽可能多的专用参数,最后选择false专门化。

例如介绍另一个版本,如:

template<class F>
struct conditional<false, int, F> { typedef int type; };

并实例化类似conditional<false, int, double>的模板类型将更喜欢专业化

template<class F> struct conditional<false, int, F>

template<class T, class F> struct conditional<false, T, F>与具有2个专门参数的版本相比更为通用。

此时有些技巧:

甚至可以声明最通用的情况(即模板的通用形式只是声明但未定义),并且只对您真正打算拥有的情况有专门化。所有非专业案例都会导致编译错误,并要求用户针对特定类型对案例进行专门化。

答案 1 :(得分:4)

  

为什么这样做?这里有什么编译规则?

我不是专家,但我会尝试从实际的角度来解释。

希望使用权利条款......

使用

template <bool B, class T, class F>
struct conditional { typedef T type; };

(但是,对于C ++ 11,我更喜欢

template <bool B, typename T, typename>
struct conditional { using type = T; };

)您声明模板

template <bool, typename, typename>
struct conditional;

并定义通用(非专用)版本。

template< class T, class F>
struct conditional<false, T, F> { typedef F type; };

(或者,在C ++ 11中,

template <typename T, typename F>
struct conditional<false, T, F> { using type = F; };

)定义conditional

的部分特化

当一个类(或结构)的模板参数匹配两个或多个定义时,编译器选择更专用的一个;所以,对于

typename std::conditional<false,int,double>::type

该类的两个定义都匹配,因此编译器选择专门的(false专门)anche typedouble

有关

typename std::conditional<true,int,double>::type a;

只有通用版本匹配,因此typeint

答案 2 :(得分:0)

在这里,大多数模板元编程的主要规则是SFINAE(替换失败不是错误)。根据此规则,如果编译器找不到类型,则它不会抛出错误,而是继续前进,并检查是否将来有任何语句可以提供类型信息。