std::piecewist_construct
針對std::map的特殊情況
map類型的emplace處理比較特殊,因爲和其他的容器不同,map的emplace函數把它接收到的所有參數都轉發給了pair的構造函數。對於一個pair來說,它既需要構造它的key又需要構造它的value。如果我們按照普通的語法使用變參模板,我們無法區分哪些參數用來構造key,哪些用來構造value。
std::map<std::string, std::complex<double>> scp;
scp.emplace("hello", 1, 2);//無法區分那個參數用來構造key,哪些參數用來構造value
所以需要一種方式既可以接受異構變長參數,又可以區分key和value,解決方式是使用c++11中提供的turple。
pair<string,complex<double>> scp(make_tuple("hello"), make_tuple(1,2));
然後這種方式是有問題的,因爲這裏有歧義,第一個tuple會被當做key,第二個tuple會被當成value,最終的結果是類型不匹配而導致對象創建失敗,爲了解決這個問題,c++11設計了piecewise_construct_t這個類型用於解決這種歧義,它是一個空類,存在的唯一目的就是解決這種歧義,全局變量std::piecewist_construct就是該類型的一個變量。所以最終的解決方式是:
pair<string,complex<double>> scp(piecewise_construct, make_tuple("hello"), make_tuple(1,2));
因爲map的emplace把參數原樣轉發給pair的構造,所以你需要使用同樣的語法來完成emplace的調用,當然你可以使用forward_as_tuple替代make_tuple,該函數會幫你構造一個tupl並轉發給pair構造。
map<string, complex<double>> scp;
scp.emplace(piecewise_construct,
forward_as_tuple("hello"),
forward_as_tuple(1, 2));
所以对于 map 来说你虽然避免了临时变量的构造,但是你却需要构建两个 tuple