2014-12-18 25 views

cevap

30

std::map<K, V> öğe türü aslında std::pair<K, V>, yani bir harita içine yerleşmesiyle zaman, tartışmalar std::pair yapicisina iletilir. Bu yüzden sadece anahtarı geçemezsiniz: std::pair<K, V> tek bir argümandan (aynı türden başka bir çift olmadıkça) yapılamaz.) Sıfır argümanları geçebilirsiniz, ancak sonra anahtar değer başlangıç ​​durumuna getirilir. Muhtemelen istediğini değil.

Çoğu durumda, hareketli değerler ucuz olacaktır (ve anahtarlar küçük ve copyable olacaktır) ve gerçekten sadece böyle bir şey yapmalıdır: V eşlenen türü olan

M.emplace(k, V{}); 

. Değer başlatılacak ve konteynere taşınacaktır. (Hareket bile seçilebilir; emin değilim.)

Hareket edemiyorsanız ve yerinde oluşturulacak olan V'a ihtiyacınız varsa, parçalı inşaat kurucusunu kullanmak zorundasınız.

M.emplace(std::piecewise_construct, std::make_tuple(k), std::make_tuple()); 

Bu k kullanılarak birinci eleman ve sıfır bağımsız değişkenleri (değer başlatma) kullanılarak ikinci elemanı oluşturmak için std::pair neden olur.

+0

Neden 'make_tuple' yerine forward_as_tuple' değil? – Yakk

+0

@Yakk Peki, bu durumda, biraz yazarak kaydetmek için. Açıkçası, forward_as_tuple 'nin gerekli olduğu durumlar var. – Brian

+9

Basit bir 'M [k];' nin 'piecewise_construct' malarkey ile aynı etkiye sahip olacağını unutmayın. –

10

Açıkça bir pair oluşturup map::emplace o geçmesi veya std::pair ait piecewise construction constructor kullanabilirsiniz.

struct foo {}; 

std::map<int, foo> m; 

m.emplace(std::pair<int, foo>(1, {})); 
m.emplace(std::piecewise_construct, 
      std::forward_as_tuple(2), 
      std::forward_as_tuple()); 

Live demo

5

std::mapstd::mutex nesnesi oluştururken aynı sorunu yaşadım. Sorun, std::mutex'un ne kopyalanabilir ne de hareketli olduğudur, bu yüzden "yerinde" oluşturmam gerekiyordu.

Kabul edilen yanıt bu durum için çalışmaz (M.emplace(k, V{}); V'nin hareketli olması gerekir). Ve karmaşık ve daha az okunabilir std::piecewise_construct seçeneğini kullanmak istemedim (diğer cevaplarda yukarıdakilere bakınız).

Çözümüm çok daha basit - sadece operator[] kullanın - varsayılan yapıcısını kullanarak değeri oluşturacak ve ona bir başvuru döndürecektir. Ya da yeni bir tane oluşturmadan mevcut öğeye bir başvuru bulup geri gönderir.

std::map<std::string, std::mutex> map; 

std::mutex& GetMutexForFile(const std::string& filename) 
{ 
    return map[filename]; // constructs it inside the map if doesn't exist 
} 
İlgili konular