簡體   English   中英

使用模板調用操作符和泛型lambdas重載結構 - gcc vs clang

[英]Overloading structs with template call operator and generic lambdas - gcc vs clang

我發現了一個代碼片段,它在clang ++ 4(和trunk)中編譯並正常工作,但無法在g ++ 7(和trunk)中編譯。 假設我有以下struct類型:

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

我想創建一個過載設定的lambda表達式出它處理a明確的,而bc都“中招”使用的通用拉姆達auto參數:

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

當我調用ol(a{})

  • clang ++編譯並按預期運行: a匹配第一個lambda,而bc匹配第二個lambda。

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

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

    似乎編譯器試圖實例化第二個lambda,即使第一個lambda是更好的匹配方式。 希望這是一個bug,因為它對我來說似乎不直觀。


請注意,如果使用一些老式的struct實例而不是lambda表達式,兩個編譯器都能正常工作:

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

這是gcc.godbolt.org的一個實例 ,展示了編譯器之間的不同行為。


這是一個g ++錯誤嗎? 或者標准中有什么東西使lambda在這種情況下的行為與struct實例不同?

我認為這是一個gcc bug(提交為80767 ),與[temp.inst] / 9運行沖突:

實現不應隱式實例化函數模板,變量模板,成員模板,非虛擬成員函數,成員類,類模板的靜態數據成員或constexpr if語句的子語句,除非這樣的實例化是必須的。

使用auto = a的通用lambda operator()的實例化不是必需的,因此不應該實例化它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM