T declval() 代替 T && declval() 表示common_type
T declval() instead of T && declval() for common_type
使用表单声明的std::declval
不是更好吗:
template< class T > T declval(); // (1)
然后是当前的:
template< class T > T && declval(); // (2)
对于std::common_type
(可能仅出于当前目的使用不同的名称)?
使用(1)
的common_type
的行为更接近三元运算符的行为(但不使用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 之后,引用的第一句也不会成立,并且会出现一些缺陷。
在 should-stdcommon-type-use-stddecay 注释中有一些关于std::common_type
问题的澄清,但这只是当前问题的背景信息。
优点
:template <class T> T&& declval();
是它适用于任何类型的T
,而简单地返回T
不适用于不可返回的类型(例如函数,数组)和不可销毁的类型(例如私有/受保护/删除析构函数,抽象基类)。
当然,差异是common_type<int, int>
最终是int&&
,然后你需要添加decay
,使common_type<int&, int&>
int
- 这也没有意义。这里只是没有胜利。
最终,我认为我们只需要一些语言功能,在未经评估的上下文中,"给我一些 T
型的东西",适用于任何T
,这确实为您提供了T
(而不是T&&
)。
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 在 QVector<std::unique_ptr 上使用 std::find<Type>>
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 使用 cmake 的 Linux 终端上的"Conversion to non-scalar type is requested"错误
- 控制到达非空函数clang(-Wreturn-type)的末尾
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- 将系数存储在头文件的数组中("does not name a type"错误)
- 尝试打开 ifstream 时出现"Incomplete type"错误
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 在"结构提升::enable_if<提升::is_pod<T>,无效>"中没有名为"type"的类型
- "Missing type specifier - int assumed"无法通过向主函数添加"return 0"来解决
- OpenCV CV_16F type
- C++ "错误:在'类 std::result_of< ... >"中没有名为'type'的类型"
- 将内存分配返回值强制转换为 TYPE 数组
- C++ 一个lambda浅拷贝const Type&如果它被赋予一个命名捕获,如[copy=val](){}?
- reference_wrapper导致"incomplete type is not allowed"
- 继承类时"invalid use of incomplete type ‘class tree_node_t’"
- 由于"error C4430: missing type specifier - int assumed. Note: C++ does not support default-int",我现在无法编
- 如何解决"'mutex' in namespace 'std' does not name a type"?
- 为什么'declval'根据'add_rvalue_reference<T>::type'而不是"T&&"来指定?