Bug 80871

Summary: Template partial ordering considered non-ambiguous with deduced and non-deduced parameter packs
Product: gcc Reporter: Barry Revzin <barry.revzin>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: UNCONFIRMED ---    
Severity: normal CC: daniel.kruegler, ed, webrown.cpp
Priority: P3 Keywords: accepts-invalid
Version: 7.1.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Barry Revzin 2017-05-23 21:29:55 UTC
Consider this example:

#ifdef VARIADIC
    template <class... Ts, class... Us> 
    constexpr int foo(Us... ) { return 1; }

    template <class... Us> 
    constexpr int foo(Us... ) { return 2; }
#else
    template <class... Ts, class U>
    constexpr int foo(U ) { return 1; }

    template <class U>
    constexpr int foo(U ) { return 2; }
#endif

int main() {
    static_assert(foo(1) == 1, "!"); 
}

Without -DVARIADIC, the call to foo(1) is considered ambiguous and the program fails to compile. But with -DVARIADIC, the program compiles. The call should be ambiguous, since Ts... does not participate in partial ordering.
Comment 1 Vittorio Romeo 2017-11-11 08:51:24 UTC
Got hit again today, while trying to write an `overload(...)` class:

    template <typename... Ts>
    struct overload : Ts...
    {
        template <typename... TFwds>
        constexpr overload(TFwds&&... xs) 
            : Ts{FWD(xs)}...
        {
        }

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

    template <typename... TFwds>
    overload(TFwds&&...) -> overload<std::decay_t<TFwds>...>;

With the code above

    auto o = overload{[]{}};

fails to compile. See: https://godbolt.org/g/Rb3ZKt
Comment 2 Ed Catmur 2019-02-18 14:42:30 UTC
See also #80438
Comment 3 Ed Catmur 2019-02-18 14:43:16 UTC
Sorry. See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80438