https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80767

            Bug ID: 80767
           Summary: Eager instantiation of member template when not
                    required
           Product: gcc
           Version: 7.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

Here's a simplifed example of overloading taking from StackOverflow question
http://stackoverflow.com/q/43982799/2069064:

template <typename... Fs> 
struct overloader : Fs...
{
    overloader(Fs... fs) 
        : Fs(fs)...
    { } 

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

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

struct CallFoo {
    auto operator()(a x) const { x.foo(); }
};

int main() {
    overloader{
#ifdef BUG
        [](a x) { x.foo(); },
#else
        CallFoo{},
#endif
        [](auto x) { x.bar(); }
    }(a{});
}

If BUG is not defined, this compiles fine. But if BUG is defined (which just
swaps a lambda for an equivalent funject), the generic lambda's call operator
is instantiated (even though the non-generic lambda should be preferred) and
the program fails to compile with:

foo.cxx: In instantiation of ‘main()::<lambda(auto:1)> [with auto:1 = a]’:
foo.cxx:26:18:   required by substitution of ‘template<class auto:1> constexpr
main()::<lambda(auto:1)>::operator decltype (((const
main()::<lambda(auto:1)>*)((const main()::<lambda(auto:1)>*
const)0))->operator()(static_cast<auto:1&&>(<anonymous>))) (*)(auto:1)() const
[with auto:1 = a]’
foo.cxx:27:10:   required from here
foo.cxx:26:24: error: ‘struct a’ has no member named ‘bar’
         [](auto x) { x.bar(); }
                      ~~^~~

Reply via email to