簡體   English   中英

emplace_back不使用std :: vector <std::map<int, int> &gt;

[英]emplace_back not working with std::vector<std::map<int, int>>

我試圖將emplace_back做成std::vector<std::map<int, int>> ,但找不到正確的語法來做到這一點。

#include<map>
#include<vector>

int main()
{
    std::vector<std::map<int, int>> v;
    std::map<int,int> a {{1,2}};

    v.push_back({{1,2}});

    v.emplace_back({1,2});    // error
    v.emplace_back({{1,2}});  // error
    v.emplace_back(({1,2}));  // error
}

push_back在這里工作,但不是emplace_back 我怎樣才能讓emplace_back工作?

emplace_back確實將所有參數轉發給成員類型的匹配構造函數。 現在, std::map有一個初始化列表構造函數,但它需要一個std::pair<const Key, Value> ,即std::pair<const int, int> push_back不是模板,因此它只需要一種類型,從而執行轉換。 也就是說,這里不會發生類型推斷。

你需要明確聲明你想擁有一個std::pair ; 以下應該有效:

#include<map>
#include<vector>

int main()
{
    std::vector<std::map<int, int>> v;

    v.emplace_back(std::initializer_list<std::pair<const int, int>>{
            {1,2},{3,4},{5,6}});

    return 0;
}

出於同樣的原因,這不編譯:

    v.emplace_back({std::pair<const int,int>(1,2),
                    std::pair<const int,int>(3,4)});

這是因為,雖然括號括起的列表可能會產生初始化列表,但它不必。 它也可以是構造函數調用或類似的東西。 所以,寫作

auto l = {std::pair<const int,int>(1,2),
          std::pair<const int,int>(3,4)};

產生l的初始化列表,但表達式本身可能以另一種方式使用:

std::pair<std::pair<const int, int>, std::pair<const int, int>> p =
          {std::pair<const int,int>(1,2),
          std::pair<const int,int>(3,4)}

整個東西有點亂。

基本上,如果你有一個大括號括號列表,它可能會產生一個初始化列表或調用匹配的構造函數。 在某些情況下,編譯器無法確定需要哪些類型; emplace_back就是其中之一(因為轉發)。 在其他情況下,它確實有效,因為所有類型都在表達式中定義。 例如:

#include <vector>
#include <utility>

int main() 
{
    std::vector<std::pair<const int, int>> v = 
         {{1,2},{3,4},{5,6}};
    return 0;
}

現在它不起作用的原因是不能推斷出任何類型。 emplace_back嘗試推斷輸入類型的名稱,但這是不可能的,因為大括號括號列表有幾種類型可以描述。 因此,沒有匹配的函數調用。

可以使用輔助函數實現如下:

 #include <map>
 #include <vector>

 void emplace_work_around(
    std::vector<std::map<int, int>>& v,
    std::initializer_list<std::pair<const int,int>> && item
 )
 {
    v.emplace_back(std::forward<std::initializer_list<std::pair<const int,int>>>(item));
 }

int main()
{
    std::vector<std::map<int, int>> v;

    emplace_work_around(v,{{1,2}});
}

問題出在我們寫的時候:

v.emplace_back({{1,2}});  // here {{1,2}} does not have a type.

編譯器無法推斷出參數的類型,也無法決定調用哪個構造函數。

根本的想法是,當你寫一個像這樣的函數

template<typename T>
void f(T) {}

並使用它

f( {1,2,3,4} ); //error

你會得到編譯器錯誤,因為{1,2,3,4}確實有類型。

但是如果你將你的功能定義為

template<typename T>
void f(std::initializer_list<T>) {}
 f( {1,2,3,4} );

然后它完美地編譯。

如果我理解這些問題報告的話,這似乎目前不受支持:

http://cplusplus.github.io/LWG/lwg-active.html#2089

http://cplusplus.github.io/LWG/lwg-active.html#2070

暫無
暫無

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

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