T declval () вместо T && declval () для common_type

Разве это не лучше использоватьstd::declval заявлено в форме:

template< class T > T declval(); // (1)

тогда текущий:

template< class T > T && declval(); // (2)

заstd::common_type (возможно, с другим именем только для этой текущей цели)?

Поведениеcommon_type с помощью(1) ближе к поведениютроичный оператор (ноне используется std::decay_t) чем поведение при использовании(2):

template< typename T >
T declval();

template <class ...T> struct common_type;

template< class... T >
using common_type_t = typename common_type<T...>::type;

template <class T>
struct common_type<T> {
    typedef T type;
};

template <class T, class U>
struct common_type<T, U> {
    typedef decltype(true ? declval<T>() : declval<U>()) type;
};

template <class T, class U, class... V>
struct common_type<T, U, V...> {
    typedef common_type_t<common_type_t<T, U>, V...> type;
};

#include <type_traits>
#include <utility>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunevaluated-expression"
int
main()
{
    int i{};
    static_assert(std::is_same< int &, decltype((i)) >{});
    static_assert(std::is_same< int  , std::common_type_t< decltype((i)), decltype((i)) > >{}); 
    static_assert(std::is_same< int &, decltype(true ? i : i) >{});
    static_assert(std::is_same< int &, common_type_t< decltype((i)), decltype((i)) > >{});

    int && k{};
    static_assert(std::is_same< int &&, decltype(k) >{});
    static_assert(std::is_same< int   , std::common_type_t< decltype(k), decltype(k) > >{}); 
    static_assert(std::is_same< int &&, decltype(true ? std::move(k) : std::move(k)) >{}); 
    static_assert(std::is_same< int &&, common_type_t< decltype(k), decltype(k) > >{});
    return 0;
}
#pragma clang diagnostic pop

Живой пример.

Каковы недостатки этого подхода? Это правда, что для(1) вdecltype() тип контекстаT должен быть конструктивным (вообще, то есть должен иметь хотя бы один конструктор) и / или разрушаемым?

Справочная статья сказал:

Для неспециализированного std :: common_type правила определения общего типа между каждой парой T1, T2 - это в точности правила определения типа возврата тернарного условного оператора в неоцененном контексте с произвольным первым аргументом типа bool и сxvalues of type T1 and T2 (since C++17) std::declval<T1>() and std::declval<T2>() (until C++17) в качестве второго и третьего операндов.The common type is the result of std::decay applied to the type of the ternary conditional (since C++14).

Я думаю, что это очень вероятно, последнее предложение (emphasized) должно быть не простоsince C++14 но такжеuntil C++17 чтобы быть справедливым. В противном случае 1-е предложение цитируется не будет даже послеC ++ 17 и какой-то дефект будет присутствовать.

Есть некоторые уточнения вдолжны-stdcommon-типа потребительная stddecay комментарии относительноstd::common_type проблемы, но это просто справочная информация для текущего вопроса.

Ответы на вопрос(1)

Ваш ответ на вопрос