【发布时间】:2014-03-25 09:50:49
【问题描述】:
给定类型A,B,我关心std::common_type<A,B> 的确切定义,忽略任意类型A... 的可变参数情况std::common_type<A...>。所以让
using T = decltype(true ? std::declval<A>() : std::declval<B>());
using C = std::common_type<A,B>;
现在,根据一些消息来源,我发现了以下关系(为简洁起见,跳过typename):
cppreference.com:
C::type = std::decay<T>::typecplusplus.com:
C::type = T-
GCC 4.8.1
李><type_traits>实现:C::type = std::decay<T>::type如果T有效,否则C不包含::type成员(“SFINAE-friendly”) Clang 3.3
<type_traits>实现:C::type = std::remove_reference<T>::type
我发现 GCC 的“SFINAE 友好”版本是一个小细节,而 std::remove_reference 和 std::decay 实际上只在内置数组和函数以及 cv 限定方面有所不同,对此我也不太关心.所以我的问题是
应该是decay<T>::type 还是只是T?使用decay<T>::type 的理由是什么?仅代表结果A() + B() 例如算术表达式?
例如,我尝试了一下,发现在“just T”定义的情况下,我们有
common_type<int&,int&> = int&
common_type<int&,long&> = long
也就是说,如果类型相等,则维护一个左值引用。这反映了这样一个事实:
int a, b;
(true ? a : b) = 0;
有效,而
int a;
long b;
(true ? a : b) = 0;
不是。这种“如果类型相等则允许赋值”的语义正是我在一个应用程序中所需要的,我倾向于认为common_type 和decay 应该是两个独立的步骤。我应该只使用我自己的定义吗?
【问题讨论】:
-
remove_reference和decay在引用类型的 cv 限定方面也不同;std::declval<A>返回一个右值引用。 -
T是旧的 (C++11),decay<T>是新的 (C++1y),可能存在与此相关的缺陷。让我看看.. -
是的,如果您需要一个可以将相同的左值引用类型统一为静态引用的版本,最好自己编写。
-
是的,它确实变得复杂,尤其是
foo。例如。给定foo f;,你可以说++f;,但不能说f = 0;。除了这种情况,我更倾向于只删除右值引用(由declval引起)并保持 cv-qualification 完好无损。无论如何,我会看看它如何与我的应用程序配合使用。
标签: c++ c++11 conditional-operator typetraits lvalue