2016-10-02 74 views
5

我在读一本书,它解释了C++特征,并且有一个例子来自C++ type_traits头文件,其中有一个奇怪的?:用法,下面是来自相应/ usr/include/C++ /的引用。 ..文件:奇怪的运算符?:decltype的用法

template<typename _Tp, typename _Up> 
    static __success_type<typename decay<decltype 
         (true ? std::declval<_Tp>() 
         : std::declval<_Up>())>::type> _S_test(int); 

撇开给出声明的目的,?:操作者的使用让我为难,在这个代码。如果第一个操作数是true,那么将始终选择std::declval<_Tp>()作为评估的结果。 该declval操作数选择如何实际工作?

编辑:最初阅读Nicolai M. Josuttis的“The C++ Standard Library:A Tutorial and Reference,2nd ed。”,第125页。但是与我的GCC头文件相比,它的格式稍微简单一些。

+1

什么是书btw? – manatttta

+0

这里重要的是表达式的类型,而不是评估哪个部分。 – Mat

+0

马特说什么。该表达式用于使用三元条件运算符类型演绎机制(您可以在这里阅读它(http://en.cppreference.com/w/cpp/language/operator_other))。 – StoryTeller

回答

9

在表达式true ? std::declval<_Tp>() : std::declval<_Up>()中总是选择第一个选项,但整个表达式必须是有效的表达式。所以std::declval<_Up>()必须是有效的,这意味着_Up必须是一个可接受零参数的可调用对象。除此之外,_Tp()_Up()必须返回相同类型(或其中一个类型必须隐式转换为另一个类型),否则三元迭代器将无法选择返回值。

这种技术被称为SFINAE(替代失败不是错误)。这个想法是,如果模板实例化失败,那么它不是一个错误,这个模板只是被忽略,编译器搜索另一个模板。

+1

只要隐式转换序列可用,它们不必返回完全相同的类型。 – StoryTeller

+0

@StoryTeller,谢谢你,我已经纠正了答案。 –

3

这里的想法是,?:要求第二个和第三个操作数具有相同的类型,或者一个类型可以转换为另一个类型。

否则,函数的实例化将失败,并选择其他一些超载。