【问题标题】:Trailing return types, decltype and const-ness尾随返回类型、decltype 和 const-ness
【发布时间】:2011-11-07 11:54:01
【问题描述】:

我只是在试验新的尾随返回类型,但我遇到了这个(简化的)代码的问题

#include <list>

class MyContainer{
  std::list<int> ints;

  auto begin( ) -> decltype(ints.begin())
  {
    return ints.begin();
  }

  auto begin( ) const -> decltype(ints.begin())
  {
    return ints.begin();
  }
};

忽略这段代码毫无意义的事实。重要的部分是使用 GCC 4.6.1 时产生的编译器错误(带有-std=c++0x 标志):

In member function 'std::list<int>::iterator MyContainer::begin() const':
error: could not convert '((const MyContainer*)this)->MyContainer::ints.std::list<_Tp, _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>, std::list<_Tp, _Alloc>::const_iterator = std::_List_const_iterator<int>]()' from 'std::list<int>::const_iterator {aka std::_List_const_iterator<int>}' to 'std::list<int>::iterator {aka std::_List_iterator<int>}'

如果您不喜欢涉及模板的错误,简短的故事是在MyContainer::beginconst 版本的主体中,表达式ints.begin() 返回一个std::list&lt;int&gt;::const_iterator 类型的值(因为ints 在这种情况下是 const)。但是,decltype(ints.begin()) 会生成 std::list&lt;int&gt;::iterator 类型,即在决定表达式的类型时,decltype 忽略begin 方法的const 限定符。不出所料,结果是类型冲突。

在我看来,这似乎是 GCC 编译器中的一个错误。只有 decltype 遵守 const 限定符并产生 const_iterator 类型才有意义。任何人都可以确认或否认(甚至可能解释)这一点吗?也许我忽略了decltype 机制中的某些内容,但这看起来是一个非常简单的场景。

注意:据我所知,同样的行为不仅适用于std::list&lt;int&gt;,还适用于任何在const-ness 上重载了返回不兼容类型的成员函数的类型。

【问题讨论】:

  • 使用 gcc 4.7.0 的最新快照编译没有错误。在那之前,我猜你还是被ints.cbegin()
  • 当然,在这种微不足道的情况下,这并不是严重的障碍,但对于 gcc 来说,正确处理所有非微不足道的情况很重要(我还想确保 I 说得对 - 我不想使用我不理解的功能)。

标签: c++ c++11 const-correctness decltype trailing-return-type


【解决方案1】:

你是对的,这是一个错误。根据 N3291 第 5.1.1 节第 3 段:

如果声明声明了类 X 的成员函数或成员函数模板,则表达式 this 是可选的 cv-qualifer-seq 和函数定义、成员声明符或声明符。它不应出现在可选的 cv-qualifier-seq 之前,并且不应出现在静态成员函数的声明中(尽管它的类型和值类别在静态成员函数中定义,因为它们在非静态成员函数中) . [注意:这是因为在知道完整的声明符之前不会发生声明匹配。 —尾注] 与其他上下文中的对象表达式不同,*this 不需要是完整类型,以便在成员函数体之外访问类成员 (5.2.5)。 [注意:只有在声明之前声明的类成员是可见的。 ——尾注]

但这是最近的工作草案和 N3291 之间的变化。所以 GCC 在不到 6 个月前是正确的。这就是根据动态规范编写代码的危险。

【讨论】:

  • 那是我的想法的一部分,因为我记得关于最后一稿的一些讨论并在尾随返回类型中使用 this,但我不确定是否有任何提案实际上被接受.感谢您提供参考充分的答案。值得庆幸的是(根据 Cubby 的评论),GCC 似乎在这方面做得很好,因为 4.7 版已经解决了这个变化。
猜你喜欢
  • 2017-08-02
  • 2017-10-08
  • 2023-03-04
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多