【问题标题】:Can type to value meta-function be used as variable alias in C++14?类型到值元函数可以用作 C++14 中的变量别名吗?
【发布时间】:2013-12-16 07:55:56
【问题描述】:

在查看 C++14 元函数别名提案 (TransformationTraits Redux, v2,N3655) 时,我注意到,不仅类型到类型的转换(例如 add_const),类型到值的元函数(例如 @ 987654325@ ) 也是类型别名。 (N3797 中不存在)。

别名类型对值元函数有什么好处吗?我认为,当存在转换操作时,可以在没有这些别名的情况下使用它们,例如 enable_if_t<is_void<T>::value,T>enable_if_t<is_void<T>{}(),T>。 (我猜is_void<T>::type::valueis_void<T>::value 一样)

如果值元函数的类型需要是别名,将它们别名为变量模板会更好吗(我没有 C++14 编译器并且从未使用过变量模板。所以语法可能是错误的)?例如别名is_void

template <class T>
constexpr bool is_void_t = is_void<T>::value;

代替

template <class T>
using is_void_t = typename is_void<T>::type;

那么就可以写enable_if_t&lt;is_void_t&lt;T&gt;,T&gt;不用boost风格enable_if,写表达会更容易(例如enable_if_t&lt;(is_void_t&lt;T&gt; || is_integral_t&lt;T&gt;),T&gt;

【问题讨论】:

  • “我没有 C++14 编译器”-coliru.stacked-crooked.com
  • @chris gcc 4.8 是否支持可变模板?看起来 gcc svn trunk 对它有一些支持。 clang 似乎也在他们的后备箱中支持它。你知道任何在线编译器有最新的 c++14 快照来测试吗?
  • Coliru 使用 SVN 版本的 Clang。
  • 我刚刚测试过,但 Coliru 的 Clang 3.4 (trunk 184460) 似乎不支持变量模板。
  • 这很奇怪,特别是考虑到标记为 SVN 的其他功能(如返回类型推导)确实有效。

标签: c++ typetraits c++14 template-aliases variable-templates


【解决方案1】:

“使用别名类型来为元函数赋值有什么好处吗?”

引用链接的 N3655,在 is_void_t 和兄弟姐妹的规范之前(第 4 页):

4 补充建议措辞

提供以下措辞是为了响应 LWG 的要求,即一致地为所有类型特征提供 ::type 成员的别名,而不仅仅是分类为 TransformationTraits 的那些.因此,本节提供了完成套装所需的规格。

这解释了为什么提案中“类型到值的元函数(例如 is_void )也是类型别名”:为了保持一致性。

此外,使用名称“is_void_<b>t</b>”来别名is_void&lt;T&gt;::<b>value</b>是错误的。 “_t”后缀始终表示类型。对于值,也许可以使用“_v”后缀。所以我们会同时拥有:

template <class T>
using is_void_t = typename is_void<T>::type;

template <class T>
constexpr bool is_void_v = is_void<T>::value;

那应该在 C++14 中编译,然后你可以写像enable_if_t&lt;(is_void_v&lt;T&gt; || is_integral_v&lt;T&gt;),T&gt; 这样的东西。但是我觉得值别名比类型一“不需要”:它没有节省太多的输入,而且,正如你所说,你可以使用短 is_void&lt;T&gt;{}() 具有相同的效果(对于 C++ 11、is_void&lt;T&gt;{} 经常够用了,感谢它的operator bool())。

【讨论】:

  • "对于 C++11,is_void&lt;T&gt;{} 通常就足够了,这要归功于它的operator bool()" 我什至会说它总是足够了 i>,因为这些特征(UnaryBinaryTypeTraits,[meta.rqmts])派生自提供此转换运算符的std::integral_constant
  • @DyP 严格来说,is_void&lt;T&gt;{}()bool,但 is_void&lt;T&gt;{} 只能隐式转换bool,这可能(很少)是“重要”的区别,例如使用重载决议或您关心确切类型的任何情况。顺便说一句,也许这就是他们为 C++14 添加operator()() 的原因? (编辑:发现this
  • @gx_ 在浏览 C++ Draft (N3797) 时,我没有找到任何对 is_void_t 等的引用,而只是对转换特征的引用。这是否意味着不接受其他别名? is_void_v 可以,但我不知道 _t 表示类型转换!
  • @abir 根据编辑报告N3692“根据 LWG 动议,提案的第 4 节未得到应用。” 来自here:“项目编辑非常担心这个扩展的添加,需要在标准中增加大约 4 页,价值有问题,因此在这个时间点将其撤回。这不代表以后就不能加了。”看来确实还是没加啊。
  • @gx_ 你说得对; n3545 中列出的两个原因是创建函数对象允许在不带隐式转换的上下文中使用,以及不使用static_cast。虽然坦率地说我不明白它们对 的含义“标准库的 enable_ifconditional 类型特征举例说明了不会产生这种隐式转换的上下文。” -- AFAIK,std::enable_if&lt;std::true_type{}&gt; 是格式良好。
猜你喜欢
  • 2014-03-14
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
相关资源
最近更新 更多