簡體   English   中英

元組到元組的 std::map 並使用 emplace

[英]std::map of tuple to tuple and using emplace

考慮以下使用 g++ 7.0.1 (-std=c++17) 編譯的代碼:

#include <map>
#include <tuple>

int main()
{
    // Create an alias for a tuple of three ints
    using ThreeTuple=std::tuple<int,int,int>;
    // Create an alias for a map of tuple to tuple (of three ints)
    using MapThreeTupleToThreeTuple=std::map<ThreeTuple,ThreeTuple>;

    MapThreeTupleToThreeTuple m;

    // The following does NOT compile
    m.emplace({1,2,3},{4,5,6});

    // ..., and neither does this
    m.emplace(std::piecewise_construct,{1,2,3},{4,5,6});
}

我原以為map::emplace()initializer_list參數就足夠了,並且會導致按照指定將元組鍵插入到元組值關聯中。 顯然,編譯器不同意。

當然,顯式創建一個元組(即ThreeTuple{1,2,3}而不僅僅是{1,2,3} )並將其傳遞給map::emplace()可以解決問題,但是為什么初始化程序不能列出直接傳遞給map::emplace() ,它會自動將它們轉發給元組構造函數?

AFAIK,在這種情況下,C++17 沒有任何變化。 正如 NathanOliver 和 Barry 所解釋的那樣, {1,2,3}不能被推斷為具有任何類型,因此不能與模板參數匹配。 您必須為ThreeTuple的構造函數提供ThreeTuple推導類型的參數,即

m.emplace(std::piecewise_construct,
          std::forward_as_tuple(1,2,3),
          std::forward_as_tuple(4,5,6));

它調用構造函數

template<typename T1, typename T2>
template<typename... Args1, typename... Args2 >
std::pair<T1,T2>::pair(std::piecewise_construct_t,
                       std::tuple<Args1...>, std::tuple<Args2...>);

在這種特殊情況下,您甚至可以省略std::piecewise_construct

m.emplace(std::forward_as_tuple(1,2,3),
          std::forward_as_tuple(4,5,6));

或(如 Nicol 在評論中指出的在 C++17 中)

m.emplace(std::tuple(1,2,3), std::tuple(4,5,6));

相當於

m.emplace(ThreeTuple(1,2,3), ThreeTuple(4,5,6));

並調用構造函數

template<typename T1, typename T2>
std::pair<T1,T2>::pair(const&T1, const&T2);

另請注意,AFAIK 您無法通過顯式使用std::initializer_list<int> 原因很簡單, pair<ThreeTuple,ThreeTuple> (地圖的value_type )沒有合適的構造函數。

但是為什么不能將初始化列表直接傳遞給map::emplace()

因為初始化列表不是表達式,所以它們沒有類型。 emplace()的簽名只是:

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );

並且您無法從{1,2,3}推斷出類型。 你不能在 C++11 中,你仍然不能在 C++1z 中。 此規則的唯一例外是如果模板參數的格式為std::initializer_list<T> ,其中T是模板參數。

為了m.emplace({1,2,3},{4,5,6}); 要工作,您需要一個簽名,例如:

std::pair<iterator,bool> emplace(key_type&&, mapped_type&&);

類似的東西可以在C++17

m.try_emplace({1,2,3},4,5,6);

暫無
暫無

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

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