使用关联容器map时遇到的一个问题(declared to take const reference, but implicit declaration would take non-const)

今天遇到一个问题,情形类似于这样:

 1 #include <iostream>
 2 #include <map>
 3 
 4 using namespace std;
 5 
 6 struct A {
 7     A() = default;
 8     //A(int a);
 9     A(A& ) = default; 
10 };
11 
12 
13 
14 
15 int main() {
16     map<int, A> m;
17     A a;
18     m[1] = a; 
19     /* 第18行报错:  
20     constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = A]’ declared to take const reference, but implicit declaration would take non-const
21        constexpr pair(const pair&) = default;
22     */
23 }

 

实际上,如果没有写17,18行,问题在第16行就会报同样的错误

原因和解决方法如下:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 struct A {
 6     A() = default;
 7     //A(int a);
 8     A(A& ) = default; // <-- const missing  (如果声明为 A(const A& ) 就没有问题)
 9 };
10 
11 template<class T>
12 struct B {
13     B() = default;
14     B(const B& ) = default;  //B<T>::B(const B<T>&) [with T = A]’ declared to take const reference, but implicit declaration would take non-const  类模板中的默认复制构造函数是内联的
15     T t;
16 };
17 
18 /* template <class T>
19 B<T>::B(const B& ) = default;  //如果不对A做改动,则需要把B的复制构函定义为非inline (这样做实际上只是掩耳盗铃。因为当我调用B的复制构函时仍会出问题) */
20 
21 int main() {
22   B<A> b;   //
23   B<A> c(b);  //采用将类模板的复制构函定义放到外面的方法时问题仍会出现
24   /* 第14行报错: B<T>::B(const B<T>&) [with T = A]’ declared to take const reference, but implicit declaration would take non-const
25      B(const B& ) = default;
26      问题原因:第22行虽然没有调用A的复制构函,但类模板的默认复制构函是inline的,所以在实例化的时候会默认生成B<T>的复制构函,而B的复制构函会将const T 作为入参调用A的复制构函,这与A的复制构函入参为非const冲突
27      */
28 }
29 
30 /* 
31 1. 如果你定义了一个类模板,用别人的类来实例化时,如果别人的类复制构函入参不是const的(而你的类模板是const),
32    则可以把你的类模板默认复制构函的定义放到模板外面(因为默认是inline)(实际上这样做问题仍存在,只要用户代码调用B的复制构函时问题就会暴露),
33    或者干脆你的类模板的复制构函入参也声明为非const(这样才真正解决问题)
34 2. 如果你定义了一个类,用别人的类模板并将这个类作为模板参数时,如果别人的模板的复制构函入参是const的,则你的类的复制构函也必须是const
35 3. 当你自己的类用作关联容器的模板参数时,也必须把类复制构函的入参声明为const (因为map的元素类型是模板类pair<>,pair的复制构函是入参为const的内联函数,如同上面的struct B)
36  */

 

posted @ 2021-12-05 13:03  大黑耗  阅读(371)  评论(0编辑  收藏  举报