const char[3] does not generate template parameter of char[3]!

The code:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<typename T1, typename T2>
struct Pair1
{
	T1 first;
	T2 second;
	Pair1(const T1& x, const T2& y) : first{ x }, second{ y } {}
};

void usePair1()
{
	const char x[3] = "hi";
	const char y[6] = "World";

	Pair1 p0{ x,y };
}



Gives me error:


'initializing': cannot convert from 'const char [6]' to 'char'



Why doesn't it decay?

Thanks
Juan
I think the issue is you can't directly copy construct an array from another array.

This would compile, but not sure if it will do what you want, since the array is not copied:
1
2
3
4
5
6
7
template<typename T1, typename T2>
struct Pair1
{
	const T1& first;
	const T2& second;
	Pair1(const T1& x, const T2& y) : first{ x }, second{ y } {}
};
It's a bit unclear what type you want here anyway so why not just be explicit?
Why not use std::string instead of a c-style char array?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <string>
#include <iostream>

template<typename T1, typename T2>
struct Pair1
{
	T1 first;
	T2 second;
	Pair1(const T1& x, const T2& y) : first {x}, second {y} {}
};

void usePair1()
{
	const std::string x {"hi"};
	const std::string y {"World"};

	Pair1 p0 {x,y};

	std::cout << p0.first << "  " << p0.second << '\n';
}

int main()
{
	usePair1();
}



If you really want to use a c-style c array, then:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <string>
#include <iostream>
#include <type_traits>

template<typename T1, typename T2>
struct Pair1
{
	const std::remove_reference_t<T1>* first;
	const std::remove_reference_t<T2>* second;
	Pair1(const T1& x, const T2& y) : first {&x}, second {&y} {}
};

void usePair1()
{
	const static char x[3] {"hi"};
	const static char y[6] {"World"};

	Pair1 p0 {x,y};

	std::cout << (char*)p0.first << "  " << (char*)p0.second << '\n';
}

int main()
{
	usePair1();
}


which displays:


hi  World


But this is 'fragile' code as first, second contain the memory addresses of x and y - which are only valid as long as x & y are in scope (hence static for x & y). Not a 'deep copy' of the contents. Also any changes to first/second are also reflected in x & y. Not recommended. Don't use c-style char arrays!
Last edited on
What I don't understand is why T1 is not deduced as char[3] -- my question is that simple...
It is deduced as const char[3]. That's not the issue. The issue is when first/second is initialised.
T1 and T2 are deduced as char, why?
The constructor receives const char[3] and const char[6].. my question is why T1 and T2 deduce as char!
T1 and T2 are deduced as char, why?
no they weren't. T1 is char[3], T2 is char[6].
clang's error message is probably more helpful
1
2
3
4
5
6
7
8
9
prog.cc:6:43: error: cannot initialize an array element of type 'char' with an lvalue of type 'char const[3]'
        Pair1(const T1& x, const T2& y) : first{ x }, second{ y } {}
                                                 ^
prog.cc:14:8: note: in instantiation of member function 'Pair1<char [3], char [6]>::Pair1' requested here
        Pair1 p0{ x,y };
              ^
prog.cc:6:56: error: cannot initialize an array element of type 'char' with an lvalue of type 'char const[6]'
        Pair1(const T1& x, const T2& y) : first{ x }, second{ y } {}
                                                              ^
ok so the compiler is not giving very clear diagnostics!
Thanks @Cubbi!

Topic archived. No new replies allowed.