2017-03-03 68 views
17
#include <vector> 
#include <iostream> 

using namespace std; 

int main() 
{ 
    vector<int> coll; 

    decltype(std::begin(std::declval<vector<int>>())) 
     pos_1 = coll.begin(); 
    auto pos_2 = coll.begin(); 

    cout << typeid(decltype(pos_1)).name() << endl; 
    cout << typeid(decltype(pos_2)).name() << endl; 
} 

Derleyicim clang 4.0. çıktısı: anlamıBöyle bir durumda neden "std :: begin()" daima "const_iterator" döndürüyor?

class std::_Vector_const_iterator<class std::_Vector_val<struct std::_Simple_types<int> > > 
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > > 

: pos_1 = pos_2; ok, pos_2 = pos_1; Tamam değil iken.

Böyle bir durumda neden yerine döndürür?

+1

Benim tahminim sen geçici kullanılarak pos_1' 'tipini deducing çünkü çünkü öyle olduğunu. Sadece const referanslarına ve tüm bunların, const'ın oyuna girdiği yere bağlanırlar. – Borgleader

cevap

21

işlev çağrısı için geçici alışkanlık bağlamak beri, daha sonra aşırı yük çözünürlüklü Type& üzerinde const Type& tercih edecektir (geçici) Type&& varsa:

std::declval<std::vector<int>>() 

std::vector<int>&& 
: olarak ifade edilebilir bir rvalue ifade

sonuç

derleyici ([iterator.range]) seçmek için std::begin iki (jenerik) aşırı yükleme yaparak sahiptir: Bir rvalue ifadesi için

template <class C> 
auto begin(C& c) -> decltype(c.begin());  // #1 

template <class C> 
auto begin(const C& c) -> decltype(c.begin()); // #2 

, sadece ikinci aşırı yük (# 2) yaşayabilir - bir rvalue bir bağlı olamaz const olmayan lvalue referansı. tip const_iterator bir örneğini verir

const_iterator begin() const noexcept; 
//      ~~~~^ 

: atıfta bulunulan tipteki const yeterlilik derleyici begin üye fonksiyon const kalifiye aşırı kullanmak anlamına gelmektedir.

Sen std::declval çağrısından std::vector<int> bir lvalue ifadesini isteyerek bu davranışı değiştirebilirsiniz:

decltype(std::begin(std::declval<std::vector<int>&>())) pos_1 = coll.begin(); 
//            ~~^~~  
+2

Dikkat çekilmesi ilginç: '' '' adlı eski olmayan '' üye '' sürümü kullanılsaydı, dönüşümlü sürümü tercih edildi ve 'yineleyici' döndürüldü. Bu tek yönlü üye ve üye olmayan işlevler farklı – KABoissonneault

+0

@KABoissonneault Yani std :: declval >(). Begin() '? Evet, bunun nedeni [\ [over.match.funcs \] /p5.1] 'dir (http://eel.is/c++draft/over.match.funcs#5.1). –

3

Eğer bir const olmayan lvalue referans

İlgili konular