为什么这种类型别名中的const限定符被删除了?

时间:2018-05-22 14:38:33

标签: c++ c++17 qualifiers

TL; DR

给出以下类型:

struct A
{
    std::vector<std::string> vec;

    using reference = std::iterator_traits<decltype(vec)::iterator>::reference;
    using const_reference = const reference;
};

为什么reference == const_reference?为什么const限定符会在第二个类型别名中删除?

请参阅godbold上不应该编译的示例。

详细

我有一个模板化的类,它将一堆迭代器(-types)作为模板参数。从这些迭代器我需要推导出引用和const引用类型,因为我有一些成员函数,如:

struct A
{
    std::vector<std::string> vec;

    using reference = std::iterator_traits<decltype(vec)::iterator>::reference;
    using const_reference = const reference;

    const_reference foo() const
    {
        return vec[0];
    }
};

通过删除const限定符,我有效地返回foo中的引用,这是非法的,因为它是一个const成员函数,因此编译器会抛出。

2 个答案:

答案 0 :(得分:7)

被删除。我们称之为&#34; const参考&#34;实际上是对const的引用 - const int&

拥有int&并添加const即可int& const。但这样的常数被删除了。

您的问题类似于const int*int* const之间的差异。除了引用之外,int&int& const属于同一类型 - const会被忽略。

答案 1 :(得分:4)

你的问题是西const。西const是坏const const const const是最好的const。

West const将const放在你想成为const的令牌的左边。东方const正在把它放在右边。

如果我告诉你永远不要在你的类型的左边放置const,并且const总是适用于左边的东西,那么看看:

using const_reference = reference const;

你可能会弄清楚const无效的原因。天真地扩展参考后,您得到string&const - 在这里您尝试将const应用于&而不是string,而foo &constfoo const&不同{1}} - foo&const仅为foo&const无法应用于引用本身,但仅适用于引用的类型。

当然,你说,但这就是我想要西方const的原因!

West const 在这里做同样的事情。它适用于&而不是string,然后被丢弃。它只是以一种更加混乱,更难以直观地掌握的方式来实现。

要理解const,请将const转换为east const。 West const只是标准east const规则的一个例外,如果左边的类型中没有令牌,则它适用于右边的令牌。此处右侧的标记是捆绑在类型别名中的整个类型string&(类型别名不是宏)。如果您键入const string&,则右侧的标记为string,您将以健全的东方风格获得string const&

东方const是最好的常量。