【发布时间】:2016-06-02 05:49:19
【问题描述】:
使用std::declval在表单中声明不是更好吗:
template< class T > T declval(); // (1)
然后是当前的:
template< class T > T && declval(); // (2)
对于std::common_type(可能仅出于当前目的使用不同的名称)?
使用(1) 的common_type 的行为比使用@987654331 时的行为更接近三元运算符(但不使用 std::decay_t)的行为@:
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 是公平的。否则即使在 C++17 之后引用的第一句也不成立,并且会出现一些缺陷。
should-stdcommon-type-use-stddecay cmets 中有一些关于std::common_type 问题的说明,但这只是当前问题的背景信息。
【问题讨论】:
-
首先,如果类型具有已删除的析构函数或无法从函数返回(例如,抽象类型、数组类型、函数类型),则会中断。
-
@T.C.我认为对于
std::common_type的当前默认实现中的这些类型 三元运算符 也没有意义,但专业化确实如此。 -
@T.C.真的,我们只需要一种语言功能,即“给我一个
T类型的表达式” -
FWIW 我一直在使用我自己的
common_type一段时间,因为我同意这是一个更明智的规范。话虽如此,对于为什么它更好,我没有硬论据,所以我无法真正回答你的问题。
标签: c++ c++11 c++14 typetraits c++17