member function already defined or declared in variadic template

I am getting this error:


'Group<std::string &>::Group(T1)': member function already defined or declared


from this code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template<typename ... T>
struct Group;

template<typename T1>
struct Group<T1>
{
	T1 t1;
	Group() = default;
	explicit Group( const T1& t) : t1{t} {}
	explicit Group( T1&& t) : t1{std::move(t)} {}
};


template<typename T1, typename...T>
struct Group<T1, T...> : Group<T...>
{
	T1 t;
	Group() = default;
	explicit Group(const T1& t1, T&&... t_) : Group<T...>(std::forward<T>(t)...),	t{ t1 } {}
	explicit Group( T1&& t1, T&&...t) : Group<T...>(std::forward<T>(t)...), t{std::move(t1)} {}
};


When I try calling them via:

1
2
3
4
5
6
7
8
9
10
11
12
template<typename ...T>
auto makeGroup(T&&...t)
{
	return Group<T...>(std::forward<T>(t)...);
}

void use()
{
	std::string s{ "Todo" };
	int a = 7;
	auto h = makeGroup(a, s);
}



I don't know what is wrong??

Last edited on
Line 19: you wrote t where you meant t_.

The other problem is more subtle. Here is a minimal example.
1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename T> struct Group
{
	explicit Group(const T&) {}
	explicit Group(T&&     ) {}
};

template<typename T> auto makeGroup(T&& t) { return Group<T>(t); }

int main()
{
	int a = 7;
	auto y = makeGroup(a);	
}


In this case makeGroup attempts to instantiate Group<int&>. The two constructors are ambiguous because these assertions hold:
1
2
3
using Q = int&;
static_assert(std::is_same_v<Q, Q const&>);
static_assert(std::is_same_v<Q const&, Q&&>);

Initially Q const& can be thought of a "reference to const reference to int", which after [dcl.ref].1 is applied and references are collapsed, is adjusted to int&:
http://eel.is/c++draft/dcl.ref#1.sentence-3
Last edited on
Thanks @mbozzi!

Topic archived. No new replies allowed.