![](/img/trans.png)
[英]how to use std::vector::emplace_back for vector<vector<int> >?
[英]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} );
然后它完美地編譯。
如果我理解這些問題報告的話,這似乎目前不受支持:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.