2017-05-15 21 views
11

我發現了一個代碼段編譯和鐺+ 4(和軀幹)正常工作,但未能在G ++ 7(和軀幹)編譯。假設我有以下struct類型:重載結構與模板調用操作和通用Lambda表達式 - GCC VS鐺

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

我想創建一個過載設置出它處理a明確lambda表達式,而bc是「捕獲」用一個auto參數的通用拉姆達:

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

當我調用ol(a{})

  • 鐺++編譯和表現如預期:a「匹配」第一個lambda,而bc匹配第二個。

  • G ++無法編譯,並出現以下錯誤:

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

    看來,編譯器試圖實例,即使第一個是一個更好的方式比賽的第二拉姆達。希望這是一個錯誤,因爲它對我來說似乎不直觀。


注意兩種編譯器正常工作,如果不是lambda表達式我使用一些老式struct實例:

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! 

我期望lambda表達式是大致相當於s0s1,所以這更令人驚訝。


這是我生產的重載集合方式:

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)...}; 
} 

而這裏的一個live example on gcc.godbolt.org,顯示了編譯器的不同的行爲。


這是一個g ++的bug嗎?或者在這種情況下,標準中是否存在使lambda表現與struct實例不同的東西?

+0

呵呵,什麼時候使用<> ...'輸入標準? C++ 17? –

+3

@NirFriedman是的,在C++ 17中,感謝[P0195](http://wg21.link/p0195) – Barry

+2

另外:能夠將函數指針作爲'overload'參數是很好的。要做到這一點,用':some_magic ...'替換':Fs ...',其中'some_magic'檢測函數指針並將其映射到存儲它的類,以及其它所有內容。 (但是也許這個過載是一個簡化的MCVE,在這種情況下忽略這個) – Yakk

回答

7

我認爲這是一個GCC的bug(提交爲80767)的[temp.inst]/9觸犯運行:

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.

的通用拉姆達的operator()auto = a不是必需的實例,因此它不應該被實例化。

+4

錯誤來自實例化轉換函數模板以指向函數,這意味着這是https://gcc.gnu.org/的另一個版本Bugzilla的/ show_bug.cgi?ID = 71117。 –