应该std :: common_type使用std :: decay吗?

时间:2014-02-23 22:55:28

标签: c++ c++11 conditional-operator typetraits lvalue

鉴于类型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.comC::type = std::decay<T>::type

  • cplusplus.comC::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_referencestd::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_typedecay应该是两个独立的步骤。我应该使用自己的定义吗?

1 个答案:

答案 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