, bu durumda tip T
Myclass&
olmak çıkarılabilir olacak - ne geçiyoruz (a
) bir lvalue olduğundan; ve referans daraltma kuralları nedeniyle, Myclass& &&
, Myclass&
değerini verir, böylece ilk kurucunuzun sahip olduğu aynı imzaya sahip olursunuz. Arama da belirsiz mi? Marc Glisse in the comments to the question ve Jonathan Wakely in the comments to this answer, tarafından sayılı belgede belirtildiği gibi, (bu cevabın orijinal versiyonunda olduğu gibi - mea culpa) olmamalıdır.
Nedeni, Standart'taki özel bir kuralın, bir değer referansını kabul eden aşırı yükün, bir rvalue referansını kabul eden aşırı yükden daha uzmanlaşmış olduğunu belirtmesidir.
belirli bir çeşit için, kesinti her iki yönde de başarılı olur (yani, tip dönüşümler yukarıda sonra özdeş olan) ve her ikisi de P ve C++ 11 Standart paragrafında 14.8.2.4/9 Ortalama bağımsız değişken şablondan türü, argüman olarak kabul edilir değildi bir lvalue bir referans ve parametre şablondan türü olsaydı -
A (yukarıdaki ifade tip yerini önce) referans türleri edildi Diğer'dan daha uzman olmak; aksi takdirde [...]
Bu derleyici bir hata (the link to the bug report soruya ilişkin yorumlarda Marc Glisse tarafından sağlanmıştır) anlamına gelir.
bu hatayı Geçici çözüm ve T&&
kabul sizin yapıcı şablon SağDeğerler geçirilen zaman sadece, bunu bu şekilde yeniden yazabilirsiniz GCC tarafından alınacak emin olmak için: Bir SFINAE-kısıtlamasını eklendi #include <type_traits>
template<typename U,
typename std::enable_if<
!std::is_reference<U>::value
>::type* = nullptr>
Myclass(U&& rvalue):i(rvalue)
{cout<<i <<" template right reference" <<endl;i++;}
Bu, derleyicinin, bir lvalue geçilirken, bu yapıcıyı aşırı yük setinden atmasını sağlar.
bir lvalue geçirildiğinde, aslında, T
bazı X
için X&
olduğu sonucuna edilecektir (expression türünde size durumunda Myclass
, pas) ve T&&
X&
içine çözer; Bir rıhtım geçilirken, diğer yandan, X
X
'dan (sizin ifade edeceğiniz ifade türünü, Myclass
davanızdan) ve T&&
X&&
'a çözecektir. SFINAE kısıtlaması, T
'un bir referans türü olup olmadığı ve bir değiştirme hatası oluşturup oluşturmadığı kontrol edilmediğinden, yapıcınızın yalnızca argüman bir ifade ifadesi olduğunda dikkate alınacağı garanti edilir.
Yani hepsini özetlemek için: İşte #include <iostream>
#include <type_traits>
class Myclass
{
int i;
public:
template<typename U>
Myclass(U& lvalue):i(lvalue)
{
std::cout << i <<" template light reference" << std::endl;
i++;
}
template<typename U,
typename std::enable_if<
!std::is_reference<U>::value
>::type* = nullptr>
Myclass(U&& rvalue):i(rvalue)
{
std::cout << i <<" template right reference" << std::endl;
i++;
}
};
int main(int argc,char*argv[])
{
Myclass a(0);
int x = 42;
Myclass b(x);
Myclass c(2);
}
bir live example olduğunu.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57172 –
@MarkTolonen 'const' olarak değiştiriliyor U & 'sonuçların çıktı 'template right reference' – yuan
çıktısı Hata 4.9 için düzeltildi, ücretsiz onunla oynamak ve yeni davranışla bulduğunuz sorunları bildirmek. –