https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78282
Bug ID: 78282 Summary: [6/7 Regression] Overload resolution failure, in parameter pack expansion, inside a template class Product: gcc Version: 6.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: kholdstare0.0 at gmail dot com Target Milestone: --- Created attachment 40009 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40009&action=edit Preprocessed source. Changing "auto" to "Key" on line 21037 fixes the issue. Hi, Apologies in advance for such a large example, I couldn't simplify it any more and trigger the behavior. Here is the minimal source: #include <tuple> #include <utility> template <typename... Ts> struct my_tuple : std::tuple<Ts...> { private: using base_t = std::tuple<Ts...>; public: using base_t::base_t; }; using std::get; #define TRIGGER_BUG 1 #if TRIGGER_BUG template <typename Key, typename... Ts> auto && get(my_tuple<Ts...>&& m) { return std::get<Key>(std::move(m)); } #else template <typename Key, typename... Ts> Key && get(my_tuple<Ts...>&& m) { return std::get<Key>(std::move(m)); } #endif namespace detail { template <typename... Ts> struct inheritor { private: using storage_type = my_tuple<Ts...>; storage_type values_; public: template <typename Derived> struct impl : private Ts::impl... { public: impl(inheritor&& unsealed) : impl(std::move(unsealed), std::index_sequence_for<Ts...>{}) { } template <size_t... indices> impl(inheritor&& outer, std::index_sequence<indices...>) : Ts::impl(get<indices>(std::move(outer.values_)))... { } }; inheritor(storage_type&& values) : values_(std::move(values)) { } }; } struct null_node { struct impl { impl(null_node&&) { } }; }; void test() { detail::inheritor<null_node> example{std::forward_as_tuple(null_node{})}; struct whatever {}; detail::inheritor<null_node>::impl<whatever> result(std::move(example)); } I have also attached the preprocessed source. Here is the example on godbolt: https://godbolt.org/g/4i1v31 Here is the error: main.cpp: In instantiation of 'detail::inheritor<Ts>::impl<Derived>::impl(detail::inheritor<Ts>&&, std::index_sequence<indices ...>) [with long unsigned int ...indices = {0ul}; Derived = test()::whatever; Ts = {null_node}; std::index_sequence<indices ...> = std::integer_sequence<long unsigned int, 0ul>]': main.cpp:46:66: required from 'detail::inheritor<Ts>::impl<Derived>::impl(detail::inheritor<Ts>&&) [with Derived = test()::whatever; Ts = {null_node}]' main.cpp:73:72: required from here main.cpp:51:56: error: no matching function for call to 'null_node::impl::impl()' : Ts::impl(get<indices>(std::move(outer.values_)))... ^~~ main.cpp:65:3: note: candidate: null_node::impl::impl(null_node&&) impl(null_node&&) { } ^~~~ main.cpp:65:3: note: candidate expects 1 argument, 0 provided main.cpp:63:9: note: candidate: constexpr null_node::impl::impl(const null_node::impl&) struct impl ^~~~ main.cpp:63:9: note: candidate expects 1 argument, 0 provided main.cpp:63:9: note: candidate: constexpr null_node::impl::impl(null_node::impl&&) main.cpp:63:9: note: candidate expects 1 argument, 0 provided It seems to be a weird interaction between "lockstep" parameter pack expansion, overload resolution and auto type deduction. Things to note: * I bring std::get into scope * my_tuple is a light wrapper around std::tuple that allows a more specific overload to be made for the get function. Note this is the get by type rather than by index. * Later in inheritor::impl I am constructing base classes by grabbing them from my_tuple using the index_sequence trick. I am calling get for indices. * The extra 'get' overload for my_tuple somehow confuses the compiler, causing it to default construct all the bases. * This problem ONLY occurs if the extra overload uses auto type deduction.