下面非常简单的代码在 C++98 中编译和链接时不会发出警告,但在 C++11 模式中会出现难以理解的编译错误。
#include <map>
struct A {
A(A& ); // <-- const missing
};
int main() {
std::map<int, A> m;
return m.begin() == m.end(); // line 9
}
错误与-std=c++11
是,gcc 版本 4.9.0 20140302(实验)(GCC):
ali@X230:~/tmp$ ~/gcc/install/bin/g++ -std=c++11 cctor.cpp
In file included from /home/ali/gcc/install/include/c++/4.9.0/bits/stl_algobase.h:64:0,
from /home/ali/gcc/install/include/c++/4.9.0/bits/stl_tree.h:61,
from /home/ali/gcc/install/include/c++/4.9.0/map:60,
from cctor.cpp:1:
/home/ali/gcc/install/include/c++/4.9.0/bits/stl_pair.h: In instantiation of ‘struct std::pair’:
cctor.cpp:9:31: required from here
/home/ali/gcc/install/include/c++/4.9.0/bits/stl_pair.h:127:17: error: ‘constexpr std::pair::pair(const std::pair&) [with _T1 = const int; _T2 = A]’ declared to take const reference, but implicit declaration would take non-const
constexpr pair(const pair&) = default;
^
使用 clang 版本 3.5(主干 202594)
ali@X230:~/tmp$ clang++ -Weverything -std=c++11 cctor.cpp
In file included from cctor.cpp:1:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/map:60:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_tree.h:63:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_algobase.h:65:
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_pair.h:119:17: error: the parameter for this explicitly-defaulted copy constructor is const, but
a member or base requires it to be non-const
constexpr pair(const pair&) = default;
^
cctor.cpp:9:22: note: in instantiation of template class 'std::pair' requested here
return m.begin() == m.end(); // line 9
^
1 error generated.
我一直在查看代码bits/stl_tree.h
我不明白为什么它试图实例化std::pair
.
为什么需要复制构造函数std::pair
在 C++11 中?
Note: the above code was extracted from Equality operator (==) unsupported on map iterators for non-copyable maps https://stackoverflow.com/q/22341818/341970.
SOLUTION
这里有两个不幸的问题。
错误消息质量差:第 8 行应该已经给出编译错误,尽管错误消息只是抱怨第 9 行。在第 8 行得到错误将非常有帮助,并且理解真正的问题会容易得多。如果 gcc / clang 主干中仍然存在此问题,我可能会提交错误报告/功能请求。
另一个问题是什么ecatmur https://stackoverflow.com/a/22359998/341970写道。考虑以下代码:
struct A {
A() = default;
A(A& ); // <-- const missing
};
template<class T>
struct B {
B() = default;
B(const B& ) = default;
T t;
};
int main() {
B<A> b;
}
它无法编译。即使任何地方都不需要复制构造函数,它仍然会被实例化,因为它默认是内联的,位于类的主体中;这会导致编译错误。这可以通过将复制构造函数移出类的主体来解决:
template<class T>
struct B {
B() = default;
B(const B& );
T t;
};
template <class T>
B<T>::B(const B& ) = default;
那么一切就都OK了。很遗憾,std::pair
有一个默认定义的内联复制构造函数。