【发布时间】: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::begin 的const 版本的主体中,表达式ints.begin() 返回一个std::list<int>::const_iterator 类型的值(因为ints 在这种情况下是 const)。但是,decltype(ints.begin()) 会生成 std::list<int>::iterator 类型,即在决定表达式的类型时,decltype 忽略begin 方法的const 限定符。不出所料,结果是类型冲突。
在我看来,这似乎是 GCC 编译器中的一个错误。只有 decltype 遵守 const 限定符并产生 const_iterator 类型才有意义。任何人都可以确认或否认(甚至可能解释)这一点吗?也许我忽略了decltype 机制中的某些内容,但这看起来是一个非常简单的场景。
注意:据我所知,同样的行为不仅适用于std::list<int>,还适用于任何在const-ness 上重载了返回不兼容类型的成员函数的类型。
【问题讨论】:
-
使用 gcc 4.7.0 的最新快照编译没有错误。在那之前,我猜你还是被
ints.cbegin() -
当然,在这种微不足道的情况下,这并不是严重的障碍,但对于 gcc 来说,正确处理所有非微不足道的情况很重要(我还想确保 I 说得对 - 我不想使用我不理解的功能)。
标签: c++ c++11 const-correctness decltype trailing-return-type