std :: conditional如何工作

alc*_*ado 10 c++ templates template-specialization template-meta-programming c++11

我们有一个这里std::conditional描述的这个小元编程奇迹.在同一参考文献中,它表示可能的实现方式

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; };
Run Code Online (Sandbox Code Playgroud)

所以如果在代码中我做了类似的事情

typename std::conditional<true,int,double>::type a;
Run Code Online (Sandbox Code Playgroud)

编译器将遵循第一个定义,如果我做了类似的事情

typename std::conditional<false,int,double>::type b
Run Code Online (Sandbox Code Playgroud)

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

ova*_*nes 8

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

在这里,编译器更喜欢更通用的类型.

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; };
Run Code Online (Sandbox Code Playgroud)

因此,如果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; };
Run Code Online (Sandbox Code Playgroud)

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

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

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

此时有些技巧:

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

  • 不错哦.非常感谢你.这种元编程技巧非常聪明,同时看起来像黑客.我想知道有一天这个type_traits将成为C++中的第一个公民,并且是由编译器以一种更简单的模板条件语言直接实现的.虽然对编译器开发人员来说可能是一个真正的挑战. (2认同)

max*_*x66 4

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

我不是专家,但我会尝试从实用的角度进行解释。

希望使用权利条款...

template <bool B, class T, class F>
struct conditional { typedef T type; };
Run Code Online (Sandbox Code Playgroud)

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

template <bool B, typename T, typename>
struct conditional { using type = T; };
Run Code Online (Sandbox Code Playgroud)

)你声明模板

template <bool, typename, typename>
struct conditional;
Run Code Online (Sandbox Code Playgroud)

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

template< class T, class F>
struct conditional<false, T, F> { typedef F type; };
Run Code Online (Sandbox Code Playgroud)

(或者,在 C++11 中,

template <typename T, typename F>
struct conditional<false, T, F> { using type = F; };
Run Code Online (Sandbox Code Playgroud)

)你定义了一个部分特化conditional

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

typename std::conditional<false,int,double>::type
Run Code Online (Sandbox Code Playgroud)

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

为了

typename std::conditional<true,int,double>::type a;
Run Code Online (Sandbox Code Playgroud)

只有通用版本匹配,所以type也是int