为什么模板引用类型不能用作模板类型别名参数?

Why can't a template reference type be used as a template typealias argument?

本文关键字:别名 参数 类型 引用类型 不能 为什么      更新时间:2023-10-16

我目前正在为自定义集合样式类编写迭代器。我有一个运行良好的可变迭代器类,但决定最好也实现一个 const 版本,该版本将阻止对其内容正在迭代的对象进行修改。我决定通过使用我在网上找到的关于使用条件类型的建议来避免单独的类和代码重复。

我以典型的 C++11 方式定义了iterator_traits类型别名,这将允许代码共享和模板参数相关的 const 或可变行为(ItemType 是外部容器类上的模板参数(:

template<bool Const = false>
class iterator {
public:
using reference = std::conditional_t<Const, const ItemType &, ItemType &>;
using pointer = std::conditional_t<Const, const ItemType *, ItemType *>;
//Rest of the iterator_traits and some other typealiases
...
template<bool _Const = Const>
std::enable_if_t<_Const, value_type>
operator*() const
{
//Return copy
}
//Non-const version
template<bool _Const = Const>
std::enable_if_t<!_Const, reference>
operator*()
{
//Return modifiable reference type
}
...
}

我决定尝试通过创建另一个模板类型别名来删除重复的std::conditional_t调用,如下所示:

template<typename type>
using const_conditional = std::conditional_t<Const, const type, type>;

并将所有std::conditional_t<...>替换为const_conditional<some_type_here>.这似乎普遍适用于外部类模板参数ItemType类型,但不适用于外部类类型本身,当其类型是引用时,如const_conditional<MyCollection<ItemType> &>.编译时,编译器抱怨我丢弃了限定符,这意味着没有应用const,因此我打破了 const 要求,但用原始代码替换我的自定义类型别名std::conditional_t代码编译和工作符合预期,我不知道为什么。

我当然可以简单地回到使用我最初使用的std::conditional_t调用,它工作正常,但它们似乎臃肿和重复,我不明白为什么我的自定义类型别名失败。在我的特定情况下,互联网上的搜索未能帮助我。任何帮助将不胜感激。

ItemType&ItemType*本身就是类型,因此添加常量限定符分别产生ItemType& const(在这种情况下,由于模板参数替换,const被静默忽略(和ItemType* const,这与预期的const ItemType&const ItemType*不同。对于后者,您可以使用:

template <typename type>
using const_conditional = std::conditional_t<Const, const type, type>;
// ...
using reference = const_conditional<ItemType>&;
using pointer = const_conditional<ItemType>*;

演示


作为旁注,_Const是一个保留标识符,就像所有其他以下划线后跟大写字母开头的标识符一样。