#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 (experimental) (GCC):
ali@X230:~/tmp$ ~/gcc/install/bin/g++ -std=c++11 cctor.cpp 在文件 /home/ali/gcc/install/include/c++/4.9.0/bits/stl_algobase.h:64:0 中包含, 来自 /home/ali/gcc/install/include/c++/4.9.0/bits/stl_tree.h:61, 来自 /home/ali/gcc/install/include/c++/4.9.0/map:60, 来自 cctor.cpp:1: /home/ali/gcc/install/include/c++/4.9.0/bits/stl_pair.h: 在‘struct std::pair’的实例化中: cctor.cpp:9:31: 从这里开始 /home/ali/gcc/install/include/c++/4.9.0/bits/stl_pair.h:127:17: 错误:‘constexpr std::pair::pair(const std::pair&) [with _T1 = const int; _T2 = A]’被声明为const引用,但隐式声明将不使用const constexpr pair(const pair&) = default; ^
clang版本为3.5 (trunk 202594)
"ali@X230:~/tmp$ clang++ -Weverything -std=c++11 cctor.cpp 文件包含自:cctor.cpp:1: 文件包含自:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/map:60: 文件包含自:/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_tree.h:63: 文件包含自:/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: 错误:显式默认的复制构造函数的参数是const,但一个成员或基类要求它为非const constexpr pair(const pair&) = default; ^ 在此请求模板类'std::pair'的实例化 return m.begin() == m.end(); // line 9 ^ 1 error generated.我一直在查看位于
bits/stl_tree.h
的代码,但我不明白为什么它要尝试实例化std::pair
。为什么它需要C++11中的
std::pair
复制构造函数?
注意:上述代码摘自Equality operator (==) unsupported on map iterators for non-copyable maps。
解决方案
这里有两个不幸的问题。
错误信息质量差:第8行应该已经给出了编译错误,尽管错误信息只在抱怨第9行。如果第8行出现错误将会非常有帮助,理解真正的问题会更容易。如果这个问题在gcc / clang trunk中仍然存在,我可能会提交一个错误报告/功能请求。
另一个问题是ecatmur所写的。考虑以下代码:
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;
一切都没问题。不幸的是,
std::pair
有一个默认的内联复制构造函数。
begin
/end
。 - dypstd::pair<int, A> p;
就足够了。 - Yakk - Adam Nevraumont