std::common_type 应该使用 std::decay 吗?
Posted
技术标签:
【中文标题】std::common_type 应该使用 std::decay 吗?【英文标题】:should std::common_type use std::decay? 【发布时间】:2014-03-25 09:50:49 【问题描述】:给定类型A,B
,我关心std::common_type<A,B>
的确切定义,忽略任意类型A...
的可变参数情况std::common_type<A...>
。所以让
using T = decltype(true ? std::declval<A>() : std::declval<B>());
using C = std::common_type<A,B>;
现在,根据一些消息来源,我发现了以下关系(为简洁起见,跳过typename
):
cppreference.com:C::type = std::decay<T>::type
cplusplus.com:C::type = T
GCC 4.8.1 <type_traits>
实现:C::type = std::decay<T>::type
如果T
有效,否则C
不包含::type
成员(“SFINAE-friendly”)
Clang 3.3 <type_traits>
实现:C::type = std::remove_reference<T>::type
我发现 GCC 的“SFINAE 友好”版本是一个小细节,而 std::remove_reference
和 std::decay
实际上只在内置数组和函数以及 cv 限定方面有所不同,对此我也不太关心.所以我的问题是
应该是decay<T>::type
还是只是T
?使用decay<T>::type
的理由是什么?仅代表结果A() + B()
例如算术表达式?
例如,我尝试了一下,发现在“just T
”定义的情况下,我们有
common_type<int&,int&> = int&
common_type<int&,long&> = long
也就是说,如果类型相等,则维护一个左值引用。这反映了这样一个事实:
int a, b;
(true ? a : b) = 0;
有效,而
int a;
long b;
(true ? a : b) = 0;
不是。这种“如果类型相等则允许赋值”的语义正是我在一个应用程序中所需要的,我倾向于认为common_type
和decay
应该是两个独立的步骤。我应该只使用我自己的定义吗?
【问题讨论】:
remove_reference
和 decay
在引用类型的 cv 限定方面也不同; std::declval<A>
返回一个右值引用。
T
是旧的 (C++11),decay<T>
是新的 (C++1y),可能存在与此相关的缺陷。让我看看..
这里是:open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#2141
是的,如果您需要一个可以将相同的左值引用类型统一为静态引用的版本,最好自己编写。
是的,它确实变得复杂,尤其是foo
。例如。给定foo f;
,你可以说++f;
,但不能说f = 0;
。除了这种情况,我更倾向于只删除右值引用(由declval
引起)并保持 cv-qualification 完好无损。无论如何,我会看看它如何与我的应用程序配合使用。
【参考方案1】:
std::common_type 应该使用 std::decay 吗?
是的,请参阅Library Working Group Defect #2141。
短版(长版,见上面的链接):
declval<A>()
返回一个A&&
common_type
是通过declval
,n3337 指定的:
template <class T, class U>
struct common_type<T, U>
typedef decltype(true ? declval<T>() : declval<U>()) type;
;
common_type<int, int>::type
因此产生int&&
,这是出乎意料的
建议的解决方案是添加decay
template <class T, class U>
struct common_type<T, U>
typedef decay_t < decltype(true ? declval<T>() : declval<U>()) > type;
;
common_type<int, int>::type
现在产生int
【讨论】:
嗯...这确实显示了我们最终如何使用decay
,所以它回答了这个问题,非常感谢。然而太糟糕了,我现在必须使用我自己的定义......是的,<int,int>
应该给int
而不是int&&
,但<int&,int&>
应该给我int&
。所以只有declval
添加的额外&&
应该被删除。
@iavr LWG 页面上的讨论包含 “common_type
的用户不希望得到引用类型作为结果” 不确定用户是谁 是,但是。
好吧,我肯定不是 :-)
呸,如果我提供参考资料,我希望得到参考资料,而且我是common_type
的用户。如果我想实现多参数链式?
的等价物,common_type
现在的行为根本不同,因为common_type
是唯一一个人们期望像std::chrono
和其他扩展这样专业化的地方,人们可以不再实现多参数链式?
。
我刚到这里是因为我希望 common_type以上是关于std::common_type 应该使用 std::decay 吗?的主要内容,如果未能解决你的问题,请参考以下文章
在啥情况下你应该更喜欢使用 std::copy 写入 cout?