2011-12-01 25 views
18

Neden geçerli Aşağıdaki kod edilir:Mükemmel bir yönlendirme işlevi neden standartlaştırılmalıdır?

template<typename T1> 
void foo(T1 &&arg) { bar(std::forward<T1>(arg)); } 

std::string str = "Hello World"; 
foo(str); // Valid even though str is an lvalue 
foo(std::string("Hello World")); // Valid because literal is rvalue 

Ama:

void foo(std::string &&arg) { bar(std::forward<std::string>(arg)); } 

std::string str = "Hello World"; 
foo(str); // Invalid, str is not convertible to an rvalue 
foo(std::string("Hello World")); // Valid 

Neden örnek 2'de lvalue örneğin 1'de yok aynı şekilde çözülmesini almaz? Ayrıca, standart neden argüman türünü std :: forward'a basit bir şekilde çıkarmayı gerektirecek şekilde sağlamasının önemli olduğunu düşünüyor? Neden? Basitçe söylemek gerekirse, türden bağımsız olarak niyet göstermektir.

Eğer bu standart bir şey değilse ve sadece derleyicim değilse, ben msvc10 kullanıyorum, bu da crappy C++ 11 desteğini açıklıyor.

Teşekkür

Düzenleme 1: literal "Merhaba Dünya" Değişti std edilecek :: bir rvalue yapmak için dize ("Merhaba Dünya").

+0

Barda ne olur? Derleme, zorunlu olarak çalıştığı anlamına gelmez. Sırasıyla void foo (T1 & arg) ve void foo (std :: string & arg) olması gerektiğine inanıyorum. – AJG85

+1

'' '' '' '' '' '' '' '' '' '' '' '' ''' Merhaba Dünya' 'bir rıhtım değil,' const char [12] 'türünde bir değerdir. – GManNickG

+0

@ AJG85 Barda ne olduğu önemli değil. && rvalue referansı demektir. – Mranz

cevap

15

Her şeyden önce, tam bir fikir edinmek için read this. (Evet, bu cevabın çoğunu başka bir yere devrediyorum.)

Özetlemek gerekirse, yönlendirme, değerlerin değer kalacağı ve rezonansların rengin kaldığı anlamına gelir. Bunu tek bir tiple yapamazsın, yani ikiye ihtiyacın var. Böylece, iletilen her bir argüman için, bu argüman için iki versiyona ihtiyacınız vardır. Bu, fonksiyon için toplam 2 N kombinasyon gerektirir. , işlevin tüm kombinasyonlarını kodlayabilir, ancak şablonlar kullanırsanız, gerektiğinde bu çeşitli kombinasyonlar sizin için oluşturulur.


böyle olduğu gibi kopya ve hamle, optimize çalışıyorsanız: durup bu şekilde yapmalıdır Sonra

struct foo 
{ 
    foo(const T& pX, const U& pY, const V& pZ) : 
    x(pX), 
    y(pY), 
    z(pZ) 
    {} 

    foo(T&& pX, const U& pY, const V& pZ) : 
    x(std::move(pX)), 
    y(pY), 
    z(pZ) 
    {} 

    // etc.? :(

    T x; 
    U y; 
    V z; 
}; 

:

struct foo 
{ 
    // these are either copy-constructed or move-constructed, 
    // but after that they're all yours to move to wherever 
    // (that is, either: copy->move, or move->move) 
    foo(T pX, U pY, V pZ) : 
    x(std::move(pX)), 
    y(std::move(pY)), 
    z(std::move(pZ)) 
    {} 

    T x; 
    U y; 
    V z; 
}; 

Sadece biri gereklidir yapıcı. Guideline: Verilerin kendi kopyasına ihtiyacınız varsa, bu kopyayı parametre listesinde yapın; Bu, arayan ve derleyiciye kopyalama veya hareket etme kararını verir.

+1

Bu yüzden, ilk örnek çalışmanın nedeni, T1'in aslında, void foo (const std :: string & & arg) ''ye eşdeğer olan void foo'yu (const std :: string & arg)' ye indirgenmesidir. kesinti kuralları? Örnek 2'de başarısız olur, çünkü dize için aşırı bir aşırı yük yoktur? Şablon işlevini tanımlamak için en iyi uygulamalar var mı, böylece türün ne olması gerektiği en azından göreceli olarak açık mı? İdeal olarak, 2^N aşırı yüklenmelerden kaçınarak, tiple açık olmak için iyi bir yol arıyorum. – Mranz

+1

@Mranz: Kesinlikle. Peki, ne için gidiyorsun? Yönlendirme ve şablonlar yönlendirme için kullanılmalıdır, gerçekten türleri bilmemelisiniz. – GManNickG

+0

"Class (.. bazı args ..., vektör items)' gibi bir vektörünü alan bir kurucum olduğunu söyleyelim. İdeal olarak, bu argümanın kopya semantiklerini kullanarak veya rengin olmasından kaçınmak için kopyaya izin vermek istiyorum. Bunu desteklemek için, öğelerin şablonunu oluşturmak ya da rutin bir aşırı yükleme oluşturmak zorunda kalacağım. Eğer şablonunu çizersem, asıl tip tanımda kaybolur ve asıl argüman, başlığımdaki dosya veya bazı yorumlar okunarak sınıfımın tüketicileri tarafından çıkarılmalıdır. – Mranz

İlgili konular