2013-09-27 15 views
11

Ben std::endluniversal reference tarafından yakalanan olmaz öğrendim basit loggerNeden bir işlev gösterici evrensel referans ile yakalanmıyor?

struct DebugOutput { 
    DebugOutput(std::ostream& out = std::cerr) : m_Out(out) {} 

    template<typename T> 
    inline DebugOutput& operator <<(T&& value) { 
     m_Out << value; 
     return *this; 
    } 
private: 
    std::ostream& m_Out; 
}; 

uygularken.

DebugOutput dbg; 
dgb << std::endl; 

Ben açıklayan bu this post Özellikle fonksiyon işaretçisi imzasını alır yapısı, yani içinde bir aşırı işlev eklemek gerekir bulundu: işlev işaretçisi evrensel tarafından yakalanan değildir Neden

typedef std::ostream& (*StandardEndLine)(std::ostream&); 
inline DebugOutput& operator<<(StandardEndLine manip) { 
    return *this; 
} 

referans ? int veya void* olarak bir tür değil mi?

+0

Bu bir şablon/aşırı yüklenmiş. – Xeo

+3

http://stackoverflow.com/a/1136617/46642 –

+0

Mümkün çoğaltıcı [std :: endl, aşırı yükleme işleci olduğunda bilinmeyen türde <<] (http://stackoverflow.com/questions/1134388/stdendl-is- bilinmeyen-tipi-aşırı-yükleyici-operatör) – Xeo

cevap

12

Bir işlev (işaretçi) evrensel bir referansa bağlanabilir. Örneğin, aşırı yüklenmiş bir işlev yapılamıyor. Eğer f, diyelim ki ikinci bir aşırı ise bunu

void f(double) {} 

çağrı foo(f) başarısız olacaktır, vardır.

Kendinizi derleyici ayakkabılarına koyun. f'u foo'a aktarmak gerekiyor ve her biri farklı bir türü olan f adında iki işlev var. Eğer türünü bilgilendirirsek, derleyici doğru şekilde f'u seçebilir. Örneğin,

foo(static_cast<void (*)(int)>(f)); 

iyi derler ve void f(int) (işlevden işaretçi dönüşümünden sonra) foo geçer. Bununla birlikte, türünü bilgilendirmiyoruz. Derleyiciden bunu çıkarmasını istiyoruz.

Benzer f için, aynı argüman nedenle adı std::endl aynı adı fakat farklı türde fonksiyonları bir dizi, tüm temsil, bu fonksiyon şablonu olduğu için std::endl için geçerlidir ve.

Şimdi, hatanın sebebinin, bir aşırı yük seti vermemiz ve tür kesintisi istememiz gerçeğidir. Bu nedenle, bu evrensel referanslar için özel değildir.

std::cout << std::endl, basic_ostream::operator << bir şablon olmadığı ve gönderilen bağımsız değişken türünü çıkarmayı denemediği için işe yarar. Bu, belirli bir tür std::endl alan bir işlevdir.

+0

Oldukça açık! Teşekkür ederim @ cassio-neri :) –

İlgili konular