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
проблемы, но это просто справочная информация для текущего вопроса.