2017-08-03 30 views
13

ile doğru işleve çözümlemiyor Bir struct/range (tuple -esque) üyelerini almak için bir ADL çözümlenmiş get kullanan bir şablon işlevini kodlamaya çalışıyorum.Neden ADL, std :: get

#include <iostream> 
#include <utility> 
#include <tuple> 

int main() { 
    auto tup = std::make_tuple(1, 2); 
    std::cout << get<0>(tup) << std::endl; 
} 

Çünkü yapılandırılmış bağlamaları önerisi (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf §11.5.3) yapı elemanları getirmesi için nasıl kullanıldığını get ilgili söylediklerinin yapıyorum. Yapıdaki öğelerden öğe almak için üye olmayan bir get kullanılır.

Ben ADL get fonksiyon std ad alanında aranılacak olan neden olacağından bu bulunacağını nerede, (o std olduğu tip std::tuple<int, int> ait olduğu argümanı çünkü) kodu yukarıdaki, derlemek olacağı varsayılmıştır. Ama bir hata alıyorum. Birisi burada doğru yaklaşımı açıklayabilir mi ve yukarıdaki kod neden çalışmaz? Bu durumda ADL'nin nasıl bir güç olması gerekir?

cevap

12

sorun sonuçta şablonları:

std::cout << get<0>(tup) << std::endl; 
//   ~~~~ 

Bu noktada derleyici, bunun t gerektiren bir işlev olduğunu bilmez. o henüz ADL kullanarak bakmak - get sadece bir isim.Ve bu isim kendi başına bir şey bulamadığı için, bu bilinmeyen bir isim olarak yorumlanacaktır. işe bu almak için, get görünür diğer bazı fonksiyon şablonu gerekir: öyle olsa bile

using std::get; 
std::cout << get<0>(tup) << std::endl; // now, OK 

şey:

template <class T> void get(); 

int main() { 
    auto tup = std::make_tuple(1, 2); 
    std::cout << get<0>(tup) << std::endl; 
} 

yapılandırılmış bağlayıcı ifadeler açıkça yüzden, bağımsız ve bağımlı aramasını kullanarak get arar

u: o [dcl.struct.bind] den, get adlı halihazırda görünen fonksiyon şablonu sahip olma ihtiyacını ortadan kaldırırget nqualified-id, E sınıf üyesi erişim aramasına göre incelenir ve en az bir bildirim bulursa, başlatıcı e.get<i>() olur. Aksi takdirde, başlatıcı get<i>(e)'dur, burada get ilişkili ad alanlarına bakılır. Her iki durumda da get<i>, şablon kimliği olarak yorumlanır. [Not: Sıradan vasıfsız arama yapılmamıştır. - son not]

Not, anahtardır. Niteliksiz bir arama yapmış olsaydık, başarısız olurduk.

+0

Çok ilginç! Yine de, bu tanımlanmamış fonksiyonu tanıtmak, başka sorunlara neden olabilir mi? Çatışmalar gibi mi? – Curious

+0

@Curious Tercih edilmeye son verilseydi. Demek istediğim, aslında bunu yapma - Sadece açıklayıcı amaçlar için buraya koyuyorum. – Barry

+0

hmmm, ADL'nin gerçekleşmesini zorlayabilmemin herhangi bir yolu var mı? 'Template' anahtar sözcüğünü denedim ama tabii ki çalışmıyor .. – Curious

11

Argüman Bağımlı Arama, aynı şekilde çalışmıyor for function templates where an explicit template argument is given.

bir işlev çağrısı sıradan arama şey, açıkça belirtilen şablon bağımsız değişken içeren bir işlev şablonuna bir işlev çağrısı bulur bile ADL yoluyla çözülebilir rağmen sıradan bulduğu şablonun bir beyan olduğunu gerektirir arama

Temelde, niteliksiz arama bir şablon işlevi bulmak için bir yol olması gerekir (aksi takdirde bir az daha karakter ve ardından bilinmeyen bir isim karşılaşmaya bir sözdizimi hatası olduğunu). Daha sonra, ADL içeri girebilir (çünkü get adı bir şablon olarak bilinir). Cppreference bir örnek verir:

namespace N1 { 
    struct S {}; 
    template<int X> void f(S); 
} 
namespace N2 { 
    template<class T> void f(T t); 
} 
void g(N1::S s) { 
    f<3>(s);  // Syntax error (unqualified lookup finds no f) 
    N1::f<3>(s); // OK, qualified lookup finds the template 'f' 
    N2::f<3>(s); // Error: N2::f does not take a non-type parameter 
       //  N1::f is not looked up because ADL only works 
       //    with unqualified names 
    using N2::f; 
    f<3>(s); // OK: Unqualified lookup now finds N2::f 
      //  then ADL kicks in because this name is unqualified 
      //  and finds N1::f 
} 

Yapılandırılmış bağlamaları özel bir durum vardır, ADL etkinken.

şu bağlamlarda

ADL okunur arama (yani, sadece ilişkili ad alanlarında arama olduğunu) yer alır:

  • fonksiyonları başlayacak ve aralık-for tarafından gerçekleştirilen end olmayan üyesinin arama üye araması başarısız olursa, döngü örnekleme noktasından bağımsız ad arama
  • .
  • olmayan üye işlev arama demet benzeri türde için yapılandırılmış bağlanma beyanı de yapılır

ilave Vurgu

+0

Std :: cout << şablonunun <0> (tup) << '\ n'' olsun ya da bir disambiguating 'template' var mı? –

+0

@DanielH Kulağa böyle bir şey teklif ederse * işe yarayabilir. [Şu anda çalışmıyor] (https://wandbox.org/permlink/dmG6fVeDQwzHvl6q) – Justin

+0

Cevabınız için teşekkürler. Her iki cevabı da kabul etmek istiyorum ama diğer cevap basit bir çözümleme tekniğinin basit bir örneğini içerdiğinden. Bunu kabul edeceğim. – Curious

İlgili konular