2016-09-02 35 views
5

std::forward'u öğreniyorum.Neden C++ dizeleri std :: forward işlevini çağırmak istemiyor?

İşte
#include <iostream> 
#include <typeinfo> 
#include <string> 
using namespace std; 

class Example { 
}; 

ostream &operator << (ostream &os, const Example &e) { os << "yes!"; return os; } 

void test_forward_inner(const Example &e) { cout << "& " << e << endl; } 
void test_forward_inner(Example &&e) { cout << "&& " << e << endl; } 

void test_forward_inner(const string &e) { cout << "& " << e << endl; } 
void test_forward_inner(string &&e) { cout << "&& " << e << endl; } 

template <typename T> 
void test_forward_wrapper(T &&arg) { 
    test_forward_inner(arg); 
} 

int main() 
{ 
    Example e; 
    test_forward_wrapper(e); 
    test_forward_wrapper(Example()); 

    cout << endl; 

    string s("hello"); 
    test_forward_wrapper(s); 
    test_forward_wrapper("hello"); 

    return 0; 
} 

ben test_forward_wrapper() den test_forward_inner() bir lvalue ve rvalue iletmek için çalıştı: Bence başka işlev çağrısına argümanları yönlendirmeden önce std::forward demiyorlar ne olacağını test etmek için küçük bir program yazdım. Bu program çalıştırıldığında çıktısı verir:

& example 
& example 

& hello 
&& hello 

std::string için s, istenen iç işlev çağrıldı fakat kendi sınıf için sadece lvalue versiyonu olarak adlandırıldı. Yalnızca argümanları iç işleve iletmeden önce std::forward'u çağırırsam, rvalue sürümünün çağrılması mümkündür.

Farkı burada yapan nedir? Bildiğim gibi, referans daraltma kurallarına göre, sarıcı Example() ile çağrıldığında, bir rengin, TExample ve arg türünün Example && türüne sahip olması, böylece iç işlevin rengin versiyonunun çağrılması gerekir.

Ve burada std::string durumu gibi diğer durumlar için iç işlevin doğru sürümü çağrıldı, ardından std::forward buradan çıkarılabilir mi? Eğer değilse, ne (belki de kötü bir şey) olur?

cevap

7

Not: "hello", std::string değil, bir const char[6]. Ve test_forward_wrapper() bir işlev şablonudur, T şablon argümanı bunun için char const (&)[6] olarak çıkarılacaktır.

test_forward_wrapper() içinde, test_forward_inner() ilk başta std::string dönüştürülmesi gerekir const char[6] ile çağrılır. Bu geçici bir std::string, yani, rvalue referansa bağlı olması tercih edilen bir rengin, bu nedenle test_forward_inner(string &&)'un çağrılmasıdır.

std::string ile test_forward_wrapper() arasındaki geçiş aynı sonucu elde edecektir.

test_forward_wrapper(std::string("hello")); 
4

fark

test_forward_wrapper("hello"); 

yılında "Merhaba" Burada std::string olmadığıdır. const char *. Bir

test_forward_wrapper(std::string("hello")); 

Ve sonuca

değiştirin bu özel sınıf en aynı olacaktır.

+1

önemli bir kısmı, iç fonksiyonu sadece 'string' oluşur' dönüşüm anlamına std :: string', kabulü, değil ise sargı, (böylece zorlama aramayýn meydana gelir) şablonu olmasıdır daha sonra (iç işleve bir r-değeri referansı sağlar), iletme söz konusu değildir. – ShadowRanger

+3

'' merhaba '' 'const char *' değil, 'const char *' haline dönüşebilen bir 'const char [6]' dır. . –

+1

^(ve bu durumda çürümez) –