簡體   English   中英

比較兩個map :: iterators:為什么需要std :: pair的拷貝構造函數?

[英]Comparing two map::iterators: why does it need the copy constructor of std::pair?

下面非常簡單的代碼在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

為什么在C ++ 11中需要std::pair的拷貝構造函數?


注意:上面的代碼是從不可復制映射的映射迭代器上不支持的Equality運算符(==)中提取的。


這里有兩個不幸的問題。

質量差的錯誤消息:第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有一個默認定義的內聯拷貝構造函數。

在這種情況下, 不需要 std::pair的復制構造函數,但由於它是在std::pair的聲明中默認定義的內聯,因此它會與std::pair本身的實例化一起自動實例化。

標准庫可以提供復制構造函數的非內聯默認定義:

template<class _T1, class _T2>
  struct pair
  {
// ...
    constexpr pair(const pair&);
// ...
  };
// ...
template<class _T1, class _T2>
constexpr pair<_T1, _T2>::pair(const pair&) = default;

但是,這不符合標准的嚴格字母(第20.3.2節),其中復制構造函數是默認的內聯定義:

  constexpr pair(const pair&) = default; 

我想我在嘗試減少錯誤后找到了它。 首先,似乎不需要進行比較以使程序格式錯誤。 然后,錯誤消息包含dtor,所以我嘗試不實例化dtor。 結果:

#include <map>

struct A {
    A(A& ); // <-- const missing
};

int main() {
    std::map<int, A>* m = new std::map<int, A>();
    // note: dtor not (necessarily?) instantiated
}

但是輸出消息仍然包含,現在對於調用m的ctor的行:

錯誤:此顯式默認的復制構造函數的參數是const,但成員或基礎要求它是非const

  constexpr pair(const pair&) = default; 

哪個提示[dcl.fct.def.default] / 4

用戶提供的顯式默認函數(即,在第一次聲明后顯式默認)是在明確默認的位置定義的; 如果將這樣的函數隱式定義為已刪除,則該程序格式錯誤

[強調我的]

如果,我認為,[class.copy] / 11表示,該構造函數應該定義為刪除,然后根據立即刪除它的定義-不僅在它的ODR使用。 因此,不應該要求實例化使程序格式錯誤。

std::map使用std::pair來存儲鍵值對,其中鍵(第一個元素)是const

編譯器錯誤與std::pair所需的拷貝構造函數有關,即使它沒有被使用(我認為它不是這樣)。

必須生成std::pair<int, A> 這是調用map :: begin時首先需要的。 由於沒有為此類型指定顯式復制構造函數,因此使用了隱式復制構造函數。

只有當 T的所有非靜態成員(類型S)都具有復制構造函數S :: S(const S&)時,隱式構造函數才會具有簽名T :: T(const T&)(對於T的基礎必須保持相同的要求)類型復制構造函數)。 否則,使用具有簽名T :: T(T&)的復制構造函數。

A的復制構造函數不符合此要求,因此std :: pair :: pair具有錯誤的STL簽名,這需要T :: T(const T&)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM