#include <vector>
int main()
{
auto v = std::vector{std::vector<int>{}}。
return v.front().empty(); //error。
}
參見在線演示
然而,根據Scott Meyers的Effective Modern C (重點在原文):
然而,如果一個或多個建構式宣告一個型別為std::initializer_list,使用括號初始化語法的呼叫 強烈推薦使用std::initializer_lists的多載。強烈地。 如果編譯器有辦法將使用括號內的初始化器的呼叫理解為 初始化器的呼叫是一個接受std::initializer_list的建構式。 編譯器將采用這種解釋。
所以,我認為
std::vector{std::vector<int>{}};應該產生一個std::vector<std::vector<int>>的物件,而不是std::vector<int>。誰錯了?以及為什么?
uj5u.com熱心網友回復:
Meyers大部分是正確的(例外的是,如果存在一個默認的建構式,那么
T{}就是值初始化),但他的宣告是關于過載解決。 這發生在 CTAD 之后,它選擇了要使用的類(以及建構式集)。CTAD 并不 "喜歡 "初始化器串列構造器,因為它更喜歡復制,而不是包裹可嵌套的模板,如
std::vector或std::optional。 (有可能通過演繹指南來覆寫這一點,但是標準庫使用默認的,正如人們所期望的那樣)。 這有一定的意義,因為它可以防止創建像std::optional<std::optional<int>>這樣的奇怪型別,但它使通用代碼更難寫,因為它給出了template< class T> void f(T x) { std::vector v{x}; / ... }一個以不規則和非注入式方式依賴于其引數型別的意義。 特別是,
v可能是std::vector<int>,而T=int或者T=std:: vector<int>,盡管是std::vector<std::deque<int>>如果T=std::deque<int>。 不幸的是,基于其他一些型別計算一種型別的工具在通用背景關系中是不能使用的。uj5u.com熱心網友回復:
auto v = std::vector{std::vector<int>{}};實際上創建了一個std::vector<int>因為它使用了std::vector拷貝建構式。它被編譯器解釋為:auto vTemp = std::vector<int>{}; auto v = std::vector<int>( vTemp ) 。所以
v最終是一個std::vector<int>,而不是一個std::vector<std::vector<int>>。正如 "P Kramer "和 "Marek P "在評論中所報告的那樣,以下語法將幫助任何編譯器完成你所期望的:
auto v = std::vector{{std::vector<int> {}}; auto v = std::vector<std::vector<int>>{ std::vector<int>{}}. };轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/314155.html
標籤:
