簡體   English   中英

如果標准容器元素類型和std :: allocator類型不同,這是錯誤的嗎?

[英]Is it wrong if the standard container element type and std::allocator type are different?

這里開始 (這是相當古老的):

用於allocator模板參數的類型和用作標准容器中的元素類型的類型一致也很重要。 例如:

 std::list<int, std::allocator<long> > // Wrong! 

不行。

以上陳述是否正確(或者是否正確)? 無論我在std::allocatorT做什么,我所做的任何測試似乎都能正常工作。 例如, std::vector<int, std::allocator<std::string>>編譯並正常工作推回和擦除元素等(根據我的理解std::allocator<std::string>::rebind<int>::other是使這項工作變得神奇的魔力。

我在這里添加一個答案,以澄清不良行為和未定義行為之間的區別。

[intro.compliance] / P1:

可診斷規則集包含本國際標准中的所有語法規則和語義規則,但那些包含“無需診斷”的明確表示法或被描述為導致“未定義行為”的規則除外。

[defns.ill.formed]:

程序不完善

[defns.well.formed]

C ++程序根據語法規則,可診斷語義規則和單定義規則(3.2)構建。

在英語中:不正確的程序應具有與之相關的診斷。 未定義的行為可以做任何事情:

  1. 它可以按照您的意圖編譯和執行。
  2. 它可以發出診斷。
  3. 它可以刪除您編寫的代碼。
  4. 它可以重新格式化最近的磁盤。

(除了第4次以外通常都會在實踐中發生)

未定義的行為非常糟糕,而imho,C和C ++標准過於寬松地應用了該規范。

從技術上講,違反Requires子句會導致未定義的行為。

[res.on.required] / P1:

違反函數的Requires:段中指定的前提條件會導致未定義的行為,除非函數的Throws:paragraph指定在違反前提條件時拋出異常。

如MSN所述, allocator_type::value_type應與表99中所述的container::value_type相同 - 可識別分配器的容器要求

allocator_type A       Requires:  allocator_type::value_type 
                                  is the same as X::value_type.

X表示一個分配器感知容器類,其value_typeT使用類型A分配器)

所以違反如下:

std::list<int, std::allocator<long> >  

是未定義的行為。 所以:

  1. 可以按照您的意圖編譯和執行。
  2. 可以發出診斷。
  3. 可以刪除您編寫的代碼。
  4. 可以重新格式化最近的磁盤。

就在最近(在我寫這篇文章的幾周內),libc ++( http://libcxx.llvm.org )已經開始用static_assert診斷這個未定義的行為,以便你盡快得到壞消息。

我們決定采用這個方向,而不是允許行為,因為容器沒有設置為允許密切相關類型之間的轉換。 例如:

std::list<int, std::allocator<long>>  list1;
std::list<int>                        list2 = list1;  // is specified to not work

即如果你開始將list1list2視為等效類型,因為std::allocator無論如何都會rebind ,當你發現這兩個列表實際上是不同的類型並且無論如何都不能進行互操作時,你會感到很失望。 所以最好盡快得到壞消息,而不是在2個月或2年之后發現,當你嘗試將它們用作等效類型時。

也許未來的標准會將list1list2視為等效類型。 它在技術上大多數可能( std::is_same可能不起作用)。 但是我沒有聽到過這方面的建議。 這個方向對我來說似乎不太可能。 使用static_assert ,錯誤很容易被診斷出來。 相反,我希望看到標准的方向是使這個代碼形成錯誤而不是未定義。 這樣做最困難的部分是字標准,而不是std :: lib實現。

編輯:在[containers.requirements.general]中,Allocator感知容器要求表明allocator_type::value_typeContainer::value_type相同。

因此,傳入具有不同value_type的allocator類型是value_type ,盡管至少有一個實現只使用allocator_traits<...>::rebind<value_type>來獲取正確的分配器。

暫無
暫無

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

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