1. 程式人生 > 其它 >使用關聯容器map時遇到的一個問題(declared to take const reference, but implicit declaration would take non-const)

使用關聯容器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 */