使用表单中声明的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。否则,即使在C++17之后,第一句的引文也不会成立,并且会出现一些缺陷。
应该-标准-类型-使用-std衰变。的评论中有一些关于std::common_type问题的澄清,但这只是当前问题的背景信息。
发布于 2016-02-21 21:16:08
以下优点:
template <class T> T&& declval();它适用于任何类型的T,而简单返回T则不适用于不可返回的类型(例如函数、数组)和不可销毁的类型(例如私有/受保护/删除的析构函数、抽象基类)。
当然,最大的优势是common_type<int, int>最终是int&&,然后您需要添加decay,这使得common_type<int&, int&>成为int --这也没有意义。这里根本就没有胜利。
最终,我认为我们只需要一些语言特性,在未评估的上下文中,它是“给我一个T类型的东西”,它适用于任何T,它确实给了您一个T (而不是T&&)。
https://stackoverflow.com/questions/35525912
复制相似问题