Belirtilen şablon parametrelerine sahip C ++ 11 make_pair derlenmiyor


85

-Std = c ++ 11 etkinken g ++ 4.7 (sonraki anlık görüntülerden biri) ile oynuyordum. Mevcut kod tabanımdan bazılarını derlemeye çalıştım ve başarısız olan bir durum biraz kafamı karıştırdı.

Biri neler olduğunu açıklayabilirse minnettar olurum.

İşte kod:

#include <utility>
#include <iostream>
#include <vector>
#include <string>

int main ( )
{
    std::string s = "abc";

    // 1 ok
    std::pair < std::string, int > a = std::make_pair ( s, 7 );

    // 2 error on the next line
    std::pair < std::string, int > b = std::make_pair < std::string, int > ( s, 7 );

    // 3 ok
    std::pair < std::string, int > d = std::pair < std::string, int > ( s, 7 );

    return 0;
}

Make_pair'in demek olduğunu anlıyorum (1) durum olarak kullanılması (türleri belirtirsem, (3) ' de kullanabilirim), ancak bu durumda neden başarısız olduğunu anlamıyorum.

Kesin hata şudur:

test.cpp: In function ‘int main()’:
    test.cpp:11:83: error: no matching function for call to ‘make_pair(std::string&, int)’
    test.cpp:11:83: note: candidate is:
    In file included from /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/utility:72:0,
                 from test.cpp:1:
    /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5:
note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
    /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5:
note:   template argument deduction/substitution failed:
    test.cpp:11:83: note:   cannot convert ‘s’ (type ‘std::string {aka std::basic_string<char>}’) to type ‘std::basic_string<char>&&’

Yine, buradaki soru sadece "neler oluyor?" Şablon özelliğini kaldırarak sorunu çözebileceğimi biliyorum, ancak sadece burada kapakların altında neyin başarısız olduğunu bilmek istiyorum.

  • g ++ 4.4 bu kodu sorunsuz bir şekilde derler.
  • -Std = c ++ 11'in kaldırılması da sorunsuz bir şekilde kodla derlenir.

6
Harika bir soru. Yine benzer C ince bir kırılma değişikliği ++ 11, başka bir örnek olarak kırılma değişim std::vectoryapı . En azından bu bir derleyici hatası verir ve anlambilimde sessiz bir değişiklik olmaz.
James McNellis

1
Bir tamsayı değişkenim varsa i. İ ve başka bir nesne ile eşleştirmek istiyorum. Makepair'i tam olarak nasıl aramalıyım? 1) make_pair <* i, obj> 2) int && j = i; make_pair <j, obj>? İkisi de çalışmıyor. Bunu yapmanın doğru yolu nedir?
PHcoDer

Yanıtlar:


136

Bu std::make_pairşekilde kullanılması amaçlanmamaktadır; şablon bağımsız değişkenlerini açıkça belirtmeniz gerekmez.

C ++ 11 std::make_pair, tipte T&&ve U&&, nerede Tve Uşablon tipi parametreler olmak üzere iki argüman alır . Etkili olarak, şöyle görünür (dönüş türünü göz ardı ederek):

template <typename T, typename U>
[return type] make_pair(T&& argT, U&& argU);

std::make_pairŞablon türü bağımsız değişkenlerini çağırıp açıkça belirttiğinizde, hiçbir bağımsız değişken kesintisi gerçekleşmez. Bunun yerine, tür bağımsız değişkenleri doğrudan şablon bildirimine ikame edilir ve sonuç olarak:

[return type] make_pair(std::string&& argT, int&& argU);

Bu parametre türlerinin her ikisinin de rvalue referansı olduğuna dikkat edin. Bu nedenle, yalnızca değerlere bağlanabilirler. Bu, geçtiğiniz ikinci argüman için sorun değil.7 geçirdiğiniz , çünkü bu bir rvalue ifadesidir. sancak bir ldeğer ifadesidir (geçici değildir ve taşınmaz). Bu, işlev şablonunun argümanlarınızla eşleşmediği anlamına gelir, bu nedenle hatayı alırsınız.

Öyleyse, şablon bağımsız değişken listesinde neyin Tve Ubulunduğunu açıkça belirtmediğinizde neden çalışıyor ? Kısacası, rvalue referans parametreleri şablonlarda özeldir. Kısmen referans daraltma adı verilen bir dil özelliğinden dolayı , bir şablon tipi parametresinin A&&olduğu türdeki bir rvalue referans parametresi, Aherhangi bir tür A.

O farketmez Abir lvalue, bir rvalue, const nitelikli bir uçucu nitelikli veya niteliksiz olduğuA&& ve bu nesneye bağlanabilir (yine, ancak ve ancak Akendisi bir şablon parametresiyse).

Örneğinizde aramayı yapıyoruz:

make_pair(s, 7)

Burada, sbir tür değeri std::stringve 7bir tür değeridirint . İşlev şablonu için şablon bağımsız değişkenlerini belirtmediğinizden, bağımsız değişkenlerin ne olduğunu bulmak için şablon bağımsız değişken çıkarımı gerçekleştirilir.

Bağlama için s, bir lvalue için T&&, derleyici tahmin eder Tolduğu std::string&tipte bir argüman, sonuçta std::string& &&. Bununla birlikte, referanslara herhangi bir referans yoktur, bu nedenle bu "çift referans" daralır std::string&. sbir eşleşmedir.

Birleşebilmelerini en basit 7için U&&: derleyici çıkarabiliriz Uolmak inttürden bir parametre veren,int&& başarıyla bağlanır, 7bir rvalue çünkü.

Bu yeni dil özellikleriyle ilgili pek çok incelik var, ancak basit bir kuralı izlerseniz oldukça kolaydır:

Bir şablon argümanı fonksiyon argümanlarından çıkarılabiliyorsa, bırakılsın. Kesinlikle gerekmedikçe argümanı açıkça belirtmeyin.

Bırakın derleyici zor işi yapsın ve% 99,9 oranında tam istediğiniz gibi olsun. İstediğiniz şey bu değilse, genellikle tanımlaması ve düzeltmesi kolay bir derleme hatası alırsınız.


6
Bu çok iyi ve kapsamlı bir açıklamadır. Teşekkür ederim!
vmpstr

1
@James - başka bir makaledeki "basit bir kural" mı yoksa okumam gereken cevap mı?
Michael Burr

4
@MichaelBurr: Hayır, bunu ben uydurdum. :-) Yani, umarım doğrudur! Sanırım doğru ... bu kural benim için neredeyse her zaman çalışıyor.
James McNellis

1
@James: teşekkürler. Etrafındaki 'alıntı kutusu', orijinal olarak başka bir yerde yazılmış bir şey olabileceğini düşündürdü. Bu cevap gerçekten bilgilendiriciydi ve başka bir yerde bir şeyi kaçırmadığımdan emin olmak istedim.
Michael Burr

2
Bu tuple'lar için de geçerli mi?
Ferruccio
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.