鉴于类型A,B
,我关注std::common_type<A,B>
的确切定义,忽略任意类型std::common_type<A...>
的可变行情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>::type
cplusplus.com:C::type = T
GCC 4.8.1 <type_traits>
实施:C::type = std::decay<T>::type
如果T
有效,否则C
不包含::type
成员(“SFINAE” - 友好“)
Clang 3.3 <type_traits>
实施:C::type = std::remove_reference<T>::type
我发现GCC的“SFINAE友好”版本是一个小细节,而std::remove_reference
和std::decay
实际上只在内置数组和函数方面有所不同,加上cv-qualification,我再次为此我并不担心。所以我的问题是
应该是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
应该是两个独立的步骤。我应该使用自己的定义吗?
答案 0 :(得分:13)
应该std :: common_type使用std :: decay?
是的,请参阅Library Working Group Defect #2141。
短版(长版,见上面的链接):
declval<A>()
返回A&&
common_type
是通过declval
,n3337:
template <class T, class U>
struct common_type<T, U> {
typedef decltype(true ? declval<T>() : declval<U>()) type;
};
common_type<int, int>::type
因此产生int&&
,这是意料之外的
建议的解决方案是添加decay
template <class T, class U>
struct common_type<T, U> {
typedef decay_t < decltype(true ? declval<T>() : declval<U>()) > type;
};
common_type<int, int>::type
现在收益int