为什么C++11类型特征不是别名模板
Why are C++11 type traits not alias templates?
类似的问题:为什么
type_traits
是用专门的模板结构而不是constexpr实现的但答案不同。
我意识到别名模板不能专门化,因此目前不能直接用于实现类型特征1。然而,这是委员会有意识的决定,据我所见,没有技术上的理由禁止这样做。
那么,将类型特征实现为别名模板,简化它们的语法,难道不是更有意义吗?
考虑
typename enable_if<is_pointer<T>::value, size_t>::type
address(T p);
与
enable_if<is_pointer<T>, size_t> address(T p);
当然,当从Boost.TypeTraits迁移时,这会带来一个突破性的界面更改——但这真的是一个大问题吗?
毕竟,代码无论如何都需要修改,因为类型位于不同的名称空间中,而且由于许多现代C++程序员不愿意打开名称空间,因此将显式限定(如果要更改的话)。
另一方面,它极大地简化了代码。考虑到模板元编程往往会变得嵌套、复杂和复杂,显然更清晰的界面是有益的。
我是不是错过了什么?如果不是,我希望得到一个不仅仅是猜测,而是依赖于(并且可以引用)对委员会决策理由的了解的答案。
1但是非常好的间接!考虑:
template <typename T> using is_pointer = typename meta::is_pointer<T>::type;
其中,meta::is_pointer<T>
对应于当前的std::is_pointer<T>
类型。
你的问题最具体的答案是:从来没有人提议过这样做。
C++标准委员会是一个由多个国家、多家公司组成的志愿者团体。你认为它是一个组织内的设计委员会。如果没有在标准草案中添加文字的建议,C++标准委员会实际上什么都做不了。
我想,没有提案的原因是类型特征是一个早期的提案,助推实施可以追溯到2000年左右。模板别名的实现较晚。许多委员会成员不愿意提出一些他们没有实施的建议。而且几乎没有机会实施你的建议。
运送C++11的压力很大。它真的打算在2009年发货,当发货日期推迟时,除了修复已经在考虑的功能外,很难对工作文件做任何事情。在某个时刻,你必须把伟大的新想法放在次要位置,以免你永远无法发货。
更新
从C++14开始,TransformationTraits(导致类型的那些)现在有模板别名拼写,例如:
template <bool b, class T = void>
using enable_if_t = typename enable_if<b,T>::type;
C++1z工作草案现在有了模板变量拼写,用于产生值的特征:
template <class T>
constexpr bool is_pointer_v = is_pointer<T>::value;
此外,即使在C++11中也可以做到:
typename enable_if<is_pointer<T>{}, size_t>::type
address(T p);
也就是说,您可以使用{}
来代替::value
(假设您的编译器支持constexpr
)。在C++14中,它变为:
enable_if_t<is_pointer<T>{}, size_t>
address(T p);
在C++1z中:
enable_if_t<is_pointer_v<T>, size_t>
address(T p);
请注意,C++1z和C++14之间的差异非常小,以至于它甚至不保存字符,只是将{}
更改为_v
,并更改放置这两个字符的位置。
与其他几个库(包括<memory>
和<functional>
)一样,类型特征是从C++TR1继承而来的。尽管这是一个不太正式的文档,但它比Boost更正式,兼容性是值得的。
此外,请注意,类型性状都源自std::integral_constant<bool>
,它确实实现了constexpr
到bool
的转换函数。这样,如果您选择的话,至少可以保存::value
零件。
作为一个完整的旁注,因为别名对std::is_pointer
:这样的特性的帮助似乎存在混淆
您可以走Boost.MPL路线,并决定使用Boost.MMP类型的积分常数,这意味着类型
template<typename Cond, typename Then = void>
using enable_if = typename std::enable_if<Cond::value, Then>::type;
// usage:
template<
typename T
, typename = enable_if<std::is_pointer<T>>
>
size_t address(T p);
或者您可以决定使用值来代替
template<bool Cond, typename Then>
using enable_if = typename std::enable_if<Cond, Then>::type;
// can use ::value
template<
typename T
, typename = enable_if<std::is_pointer<T>::value>>
>
size_t address(T p);
// or constexpr conversion operator
template<
typename T
, typename = enable_if<std::is_pointer<T> {}>
>
size_t address(T p);
请注意,在后一种情况下,不可能使用enable_if<std::is_pointer<T>()>
:std::is_pointer<T>()
是一种函数类型(采用void
并返回std::is_pointer<T>
),并且是无效的,因为在这种情况下,我们的别名采用值而不是类型。大括号确保它是一个常量表达式。
正如您可能已经注意到的,std::is_pointer
根本没有从模板别名中获益。这并不奇怪,因为有趣的部分是访问::value
,而不是::type
:模板别名只能帮助处理成员类型。std::is_pointer
的type
成员并不有趣,因为它是Boost.MPL型积分常数(在本例中为std::true_type
或std::false_type
),所以这对我们没有帮助。对不起!
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- C++ 11 个模板,参数包的别名
- C++11 模板解析错误,使用模板别名键入推导
- c++11 严格别名规则是否允许通过 char *、char(&)[N],甚至 std::array<char、N> 和 -fstrict-aliasing -Wstrict-aliasi
- Doxygen 对 C++11 模板别名的支持("using"语法)?
- C++11中一个专用模板的名称别名
- C++11`using`关键字:专门化模板参数的模板别名
- 在 C++11 中使用严格的混叠时,它是否定义为 _write_ 到 char*,然后从别名的非 char* 读取_
- C++11 模板函数别名与包装器
- C++11 模板别名作为模板模板参数会导致不同的类型
- C++11 模板类型别名以减少痛苦
- C++11:如何对函数进行别名
- 为什么C++11类型特征不是别名模板
- c++ 11在CUDA中的别名模板
- c++ 11中的const类型转换为const别名
- 当基类具有两个或多个模板参数时,C++11 别名基模板类变量在模板派生类中不起作用
- 如何在c++ 11中使用右值复制或别名对象
- 如何在C++11中访问可能不存在的类型别名
- C++11中的别名结构
- C++11 别名和模板模板