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

iav*_*avr 16 c++ conditional-operator lvalue type-traits c++11

鉴于类型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>;
Run Code Online (Sandbox Code Playgroud)

现在,根据一些消息来源,我发现了以下关系(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

我找到"SFINAE友好"版本的GCC的一个小细节,而std::remove_referencestd::decay实际上仅在内置阵列和功能,加上CV-资格有所区别,这再次我不关心了.所以我的问题是

应该是decay<T>::type还是只是T?使用的理由是decay<T>::type什么?它只是关于表示结果,A() + B()例如算术表达式吗?

例如,尝试了一下,我发现在"正义T"定义的情况下,我们有

common_type<int&,int&> = int&
common_type<int&,long&> = long
Run Code Online (Sandbox Code Playgroud)

也就是说,如果类型相等,则保持左值引用.这反映了这一事实

int a, b;
(true ? a : b) = 0;
Run Code Online (Sandbox Code Playgroud)

是有效的,而

int a;
long b;
(true ? a : b) = 0;
Run Code Online (Sandbox Code Playgroud)

不是.的"允许转让,如果类型相同"这个语义正是我需要在一个应用程序,我倾向于认为,common_typedecay应两个独立的步骤.我应该使用自己的定义吗?

dyp*_*dyp 13

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

是的,请参阅图书馆工作组缺陷#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;
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 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;
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • common_type<int, int>::type 现在收益率 int

  • Bah,如果我输入引用,我希望得到一个引用,并且我是`common_type`的用户.如果我想实现等价的多参数链接`?`,`common_type`现在的行为基本不同,而`common_type`是唯一一个需要专门化`std :: chrono`和其他扩展名的地方,人们不能再实现一个多链接的链接```. (4认同)