[Bug c++/78282] New: [6/7 Regression] Overload resolution failure, in parameter pack expansion, inside a template class
kholdstare0.0 at gmail dot com
gcc-bugzilla@gcc.gnu.org
Wed Nov 9 20:15:00 GMT 2016
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.
More information about the Gcc-bugs
mailing list