2013-12-14 30 views
11

Derleyici bir şikayeti bir rengin referansına bağlama girişiminde bulunduğumu şikayet ediyor ancak nasıl göremiyorum. Ben C++ 11 için yeni, semantik vb. Taşıyorum, lütfen benimle birlikte ol. Bu yöntemi çağırırReferans bağlayıcısını yeniden adlandırmak için Lvalue

template <typename Key, typename Value, typename HashFunction, typename Equals> 
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key&& key) 
{ 
    // Some code here... 

    Insert(key, Value()); // Compiler error here 

    // More code here. 
} 

:

template <typename Key, typename Value, typename HashFunction, typename Equals> 
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key&& key, Value&& value) 
{ 
    // ... 
} 

aşağıdaki gibi elde hataları tutmak: Ekle() çağrı

cannot convert argument 1 from 'std::string' to 'std::string &&' 

Ben bu işlevi var. Operatör aşırı yükünde bir değer olarak tanımlanan key mu değil mi? Neden bir değer olarak yeniden yorumlanıyor?

Teşekkürler. Burada

cevap

18
Insert(key, Value()); // Compiler error here 

keyKey&& key - bu bir lvalue olduğunu! Bir ismi var ve adresini alabilirsin. Sadece bu türden bir değer, "Key için rvalue referansı" dır.

Bir rvalue geçmek gerekir ve bunun için std::move kullanmak gerekir: Bu sezgilere neden görebilirsiniz

Insert(std::move(key), Value()); // No compiler error any more 

! Fakat bir kere referansı (bir referansa bağlı bir referans olan) ve gerçek bir değeri ayırt edip yeniden referansladığınızda, daha net hale gelir.

Düzenleme: Burada asıl sorun, rvalue referanslarını kullanmaktır. Onları argüman türünün çıkarıldığı bir işlev şablonunda kullanmak mantıklıdır çünkü bu, argümanın referans çöküş kuralları nedeniyle bir değer referansına veya bir referans referansına bağlanmasını sağlar. Neden bu makaleyi ve videoyu izleyin: http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

Ancak, bu durumda, FastHash<std::string, ... > örneğini oluşturduğunuzda zaten sınıf tarafından belirlendiği için, işlev çağrıldığında Anahtar türü çıkarılmaz. Bu nedenle, gerçekten de rvalue referanslarının kullanılmasını emrediyorsunuz ve bu nedenle std::move kodunu kullanarak düzeltmeleri yapıyorsunuz.

Ben parametreler değeriyle almak olduğunu için kodunuzu değiştirecek:

template <typename Key, typename Value, typename HashFunction, typename Equals> 
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key key) 
{ 
    // Some code here... 

    Insert(std::move(key), Value()); 

    // More code here. 
} 

template <typename Key, typename Value, typename HashFunction, typename Equals> 
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key key, Value value) 
{ 
    // ... 
} 

değer bağımsız değişkenlerinin kullanımı nedeniyle fazladan kopya konusunda çok fazla endişe etmeyin - bunlar sıklıkla derleyici tarafından dışarı optimize edilmiştir.

+2

Sadece "Anahtar" lvalenin türü değil midir? Rvalue-reference-ness hala nasıl korunur? – hvd

+0

Bu, ancak hvd'nin geliştirdiği sorunu anladığından emin değilim. Açıklar mısınız? –

+0

@hvd Korunan bir argüman türü kesintisi olmadığından korunur - düzenlememe bakın. – polkadotcadaver

İlgili konular