2017-05-15 50 views
11
Ben derler ve clang ++ 4 (ve gövde) düzgün çalışır ancak g ++ 7 (ve gövde) içinde derlenmeyecektir bir kod parçası keşfettiler

vs gcc. en aşağıdaki struct türleri vardır varsayalım:Aşırı yükleme yapılar - clang

struct a { void foo() { } }; 
struct b { void bar() { } }; 
struct c { void bar() { } }; 

b ve c bir auto parametresini kullanarak genel bir lambda'da "yakalanmış" iken ben, bir aşırı yük açıkça a kolları lambdas dışına set oluşturmak istiyorum:

auto ol = overload([](a x) { x.foo(); }, 
        [](auto x){ x.bar(); }) 

ben çağırmak ol(a{}):

  • clang ++, derleme ve beklendiği gibi davranır: a, "birinci" lambda eşleşirken, b ve c, ikinci olanı eşleştirir.

  • gr ++ aşağıdaki hata ile, derlenmeyecektir:

    error: 'struct a' has no member named 'bar' 
          [](auto x){ x.bar(); }; 
             ~~^~~ 
    

    derleyici İlki yolu iyi bir eşleşme olsa da ikinci lambda örneğini çalışır gibi görünüyor. Umarım bu bir hatadır, çünkü bana görünmez gibi geliyor. Ben lambda'lar s0 kabaca eşdeğer olması beklenebilir

    struct s0 
    { 
        auto operator()(a x) const { x.foo(); } 
    }; 
    
    struct s1 
    { 
        template <typename T> 
        auto operator()(T x) const { x.bar(); } 
    }; 
    
    auto os = overload(s0{}, s1{}); 
    os(a{}); // OK! 
    

    ve: yerine lambda Bazı eski moda struct örneklerini kullanmak ifadelerde ise


Not hem derleyiciler düzgün çalışması s1, bu daha da şaşırtıcı.


Bu

ben aşırı yük setini üreten ediyorum yoludur:

template <typename... Fs> 
struct overloader : Fs... 
{ 
    template <typename... FFwds> 
    overloader(FFwds&&... fs) : Fs{std::forward<FFwds>(fs)}... 
    { 
    } 

    using Fs::operator()...; 
}; 

template <typename... Fs> 
auto overload(Fs&&... fs) 
{ 
    return overloader<std::decay_t<Fs>...>{std::forward<Fs>(fs)...}; 
} 

Ve burada derleyici arasında farklı davranış gösteren bir live example on gcc.godbolt.org bu.


Bu bir g ++ hatası mı? Veya standart olarak lambdaların bu durumda struct örneğinden farklı davranmasını sağlayan bir şey var mı?

+0

Huh, ne zaman kullandı <> ...'standart girmek? C++ 17? –

+3

@NirFriedman Yep, C++ 17 sayesinde, [P0195] sayesinde (http://wg21.link/p0195) – Barry

+2

Bir kenara: 'aşırı yüke' argüman olarak işlev göstergelerini kullanabilmek güzeldir. Bunu yapmak için, ': Fs ... 'yerine:' some_magic' ... 'ile,' 'some_magic' işlev işaretleyicilerini algılar ve onu depolayan bir sınıfa ve onun dışındaki her şeyi tek başına bırakır. (Ancak bu aşırı yüklenme, basitleştirilmiş bir MCVE'dur, bu durumda bunu görmezden gelir) – Yakk

cevap

7

Bu [temp.inst]/9 uyulmadığını çalışan, (80767 olarak gönderilen) bir gcc hata olduğunu düşünüyorum:

An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement, unless such instantiation is required.

jenerik lamda en operator()auto = a ile gerekli değildir örneğinin, dolayısıyla bunun örneği edilmemelidir.

+4

Hata, dönüştürme işlevi şablonunu işaretçiden işleve dönüştürmekten kaynaklanır, yani bu, başka bir https://gcc.gnu.org/ sürümüdür bugzilla/show_bug.cgi? id = 71117. –

İlgili konular