 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Maciej Sobczak Guest
|
Posted: Fri Feb 17, 2006 4:06 pm Post subject: Template deduction fails, except when it succeeds |
|
|
Hi,
Consider:
template<class E>
void foo(const E (&tab)[5]) {}
template<class E>
void bar(const E *) {}
int main()
{
char tab[5];
foo(tab); // 1
bar(tab); // 2
}
1. fails, 2. is OK.
When I try to explain 1, my reasoning breaks down because of 2.
And the other way round.
What exactly makes one fail and the other succeed? What are the allowed
conversions in which context?
Please refer to standard paragraphs for justification.
Regards,
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Fri Feb 17, 2006 5:07 pm Post subject: Re: Template deduction fails, except when it succeeds |
|
|
Maciej Sobczak wrote:
| Quote: | Consider:
template<class E
void foo(const E (&tab)[5]) {}
template<class E
void bar(const E *) {}
int main()
{
char tab[5];
foo(tab); // 1
bar(tab); // 2
}
1. fails, 2. is OK.
When I try to explain 1, my reasoning breaks down because of 2.
And the other way round.
What exactly makes one fail and the other succeed? What are the allowed
conversions in which context?
Please refer to standard paragraphs for justification.
|
14.2.8.4/9
"T*" is there, "T(&)[]" is not.
V
--
Please remove capital As from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Matti Rintala Guest
|
Posted: Fri Feb 17, 2006 6:06 pm Post subject: Re: Template deduction fails, except when it succeeds |
|
|
Maciej Sobczak wrote:
| Quote: | template<class E
void foo(const E (&tab)[5]) {}
template<class E
void bar(const E *) {}
int main()
{
char tab[5];
foo(tab); // 1
bar(tab); // 2
}
1. fails, 2. is OK.
What exactly makes one fail and the other succeed? What are the allowed
conversions in which context?
Please refer to standard paragraphs for justification.
|
14.8.2.1 1-3:
"Template argument deduction is done by comparing each function template
parameter type (call it P) with the type of the corresponding argument of
the call (call it A) as described below.
If P is not a reference type:
— If A is an array type, the pointer type produced by the array-to-pointer
standard conversion (4.2) is used in place of A for type deduction; otherwise,
— If A is a function type, the pointer type produced by the
function-to-pointer standard conversion (4.3) is used in place of A for
type deduction; otherwise,
— If A is a cv-qualified type, the top level cv-qualifiers of A’s type are
ignored for type deduction."
The first bullet covers your case. Array-to-pointer conversion is used
before template argument deduction.
--
------------- Matti Rintala ------------ matti.rintala (AT) tut (DOT) fi ------------
Painting is the art of inclusion. Photography is an art of exclusion.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Fri Feb 17, 2006 8:39 pm Post subject: Re: Template deduction fails, except when it succeeds |
|
|
* Matti Rintala:
| Quote: | Maciej Sobczak wrote:
template<class E
void foo(const E (&tab)[5]) {}
template<class E
void bar(const E *) {}
int main()
{
char tab[5];
foo(tab); // 1
bar(tab); // 2
}
1. fails, 2. is OK.
What exactly makes one fail and the other succeed? What are the allowed
conversions in which context?
Please refer to standard paragraphs for justification.
14.8.2.1 1-3:
"Template argument deduction is done by comparing each function template
parameter type (call it P) with the type of the corresponding argument of
the call (call it A) as described below.
If P is not a reference type:
— If A is an array type, the pointer type produced by the array-to-pointer
standard conversion (4.2) is used in place of A for type deduction; otherwise,
— If A is a function type, the pointer type produced by the
function-to-pointer standard conversion (4.3) is used in place of A for
type deduction; otherwise,
— If A is a cv-qualified type, the top level cv-qualifiers of A’s type are
ignored for type deduction."
The first bullet covers your case. Array-to-pointer conversion is used
before template argument deduction.
|
Nope. The function template parameter P /is/ a reference type. Hence
the first point does not apply, at least not at first...
The Holy Standard then goes on to state
"If P is a cv-qualified type, the top level cv-qualifiers of P's type
are ignored for type deduction. If P is a reference type, the type
referred to by P is used for type deduction".
The last sentence means P = const E (&)[5] is first transformed to
P = const E[5], then this is matched against the argument type
A = int[5].
Apparently there can be no type E such that const E = int, and that
would then be a formalistic argument that the foo call above should not
compile.
But consider
template< typename E >
void bar( E const * ) {}
int main()
{
int x;
bar( &x );
}
This is /accepted/ by Comeau Online (Comeau being the only compiler I
know that does not accept the OP's foo call). And it is accepted by
MSVC 7.1 and by g++ 3.4.4, in sum, by the three compilers I tested this
on. So apparently there's no problem matching const E = int, but it
beats me where in the standard we get that from.
And I think that was the OP's point (the E const* example in the OP's
post indicates that).
Conclusion: compilers disagree, with as far as I know Comeau the only
one that doesn't accept the common idiom, and so far no posting in this
thread has demonstrated clearly which is correct, if any. I think this
is simply a bug in the Comeau compiler or perhaps the EDG front end.
And if not, then it's a bug in the standard... ;-)
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Maciej Sobczak Guest
|
Posted: Mon Feb 20, 2006 8:06 pm Post subject: Re: Template deduction fails, except when it succeeds |
|
|
Victor Bazarov wrote:
| Quote: | Consider:
template<class E
void foo(const E (&tab)[5]) {}
template<class E
void bar(const E *) {}
int main()
{
char tab[5];
foo(tab); // 1
bar(tab); // 2
}
1. fails, 2. is OK.
When I try to explain 1, my reasoning breaks down because of 2.
And the other way round.
What exactly makes one fail and the other succeed? What are the
allowed conversions in which context?
Please refer to standard paragraphs for justification.
14.2.8.4/9
"T*" is there, "T(&)[]" is not.
|
Then, why the following works?
template<class E>
void foo(E (&tab)[5]) {}
Above, E will be correctly deduced.
In the case of array, it's const which makes a difference between
failure and success. With pointers, const does not seem to be an
obstacle at all.
I still don't see any convincing explanation for the failure in one
place and success in another.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Tue Feb 21, 2006 1:06 am Post subject: Re: Template deduction fails, except when it succeeds |
|
|
Maciej Sobczak wrote:
| Quote: | Victor Bazarov wrote:
Consider:
template<class E
void foo(const E (&tab)[5]) {}
template<class E
void bar(const E *) {}
int main()
{
char tab[5];
foo(tab); // 1
bar(tab); // 2
}
1. fails, 2. is OK.
When I try to explain 1, my reasoning breaks down because of 2.
And the other way round.
What exactly makes one fail and the other succeed? What are the
allowed conversions in which context?
Please refer to standard paragraphs for justification.
14.2.8.4/9
"T*" is there, "T(&)[]" is not.
Then, why the following works?
|
Probably because your 'tab' is an array of _non_const_ char. Just
a possibility, really. A glimpse of a hint of an idea, really.
| Quote: | template<class E
void foo(E (&tab)[5]) {}
Above, E will be correctly deduced.
In the case of array, it's const which makes a difference between
failure and success. With pointers, const does not seem to be an
obstacle at all.
|
There is no conversion between an array of non-const [T] and
a reference to an array of const [T]. There is, however, conversion
between a pointer to T and a pointer to const T.
| Quote: | I still don't see any convincing explanation for the failure in one
place and success in another.
|
I don't seem to have any.
V
--
Please remove capital As from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Tue Feb 21, 2006 3:15 pm Post subject: Re: Template deduction fails, except when it succeeds |
|
|
* Victor Bazarov:
| Quote: |
There is no conversion between an array of non-const [T] and
a reference to an array of const [T].
|
It seems current compilers are not as enlightened... ;-)
Consider
int main()
{
int a[5] = {};
int const (&ra)[5] = a;
}
This compiles fine with MSVC 7.1, g++ 3.4.4, and Comeau Online 4.3.3.
Perhaps you -- or someone -- could provide some reference(s) to the
standard why all three compilers are wrong?
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Tom Widmer Guest
|
Posted: Tue Feb 21, 2006 3:17 pm Post subject: Re: Template deduction fails, except when it succeeds |
|
|
Maciej Sobczak wrote:
| Quote: | Hi,
Consider:
template<class E
void foo(const E (&tab)[5]) {}
template<class E
void bar(const E *) {}
int main()
{
char tab[5];
foo(tab); // 1
bar(tab); // 2
}
1. fails, 2. is OK.
When I try to explain 1, my reasoning breaks down because of 2.
And the other way round.
What exactly makes one fail and the other succeed? What are the allowed
conversions in which context?
Please refer to standard paragraphs for justification.
|
The important bits for bar(tab) are 14.8.2.1/2 first bullet and /3, 2nd
bullet:
1 "If A is an array type, the pointer type produced by the
array-to-pointer standard conversion (4.2) is used in place of A for
type deduction; otherwise,"
2 "A can be another pointer or pointer to member type that can be
converted to the deduced A via a qualification conversion (4.4)."
So, A is char[5], so char* is used by 1. But P is const E*, so E ==
char is deduced, since 2 allows a difference in cv qualification for
pointers.
As for foo, others have already explained that.
Tom
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Maciej Sobczak Guest
|
Posted: Thu Feb 23, 2006 4:06 pm Post subject: Re: Template deduction fails, except when it succeeds |
|
|
Victor Bazarov wrote:
| Quote: | 14.2.8.4/9
"T*" is there, "T(&)[]" is not.
Then, why the following works?
Probably because your 'tab' is an array of _non_const_ char. Just
a possibility, really. A glimpse of a hint of an idea, really.
There is no conversion between an array of non-const [T] and
a reference to an array of const [T]. There is, however, conversion
between a pointer to T and a pointer to const T.
|
typedef int array_of_int[5];
typedef int const array_of_const_int[5];
void foo(array_of_const_int &) {}
void bar(
int main()
{
array_of_int a = {1, 2, 3, 4, 5};
array_of_const_int &ca = a; // OK
foo(a); // OK
}
The above works fine (Comeau, g++), so the compiler is able to bind a
reference to an array of const given an array of non-const.
I'm asking what prevents it from deducing the type when templates are
involved. It's not the lack of conversion.
| Quote: | I still don't see any convincing explanation for the failure in one
place and success in another.
I don't seem to have any.
|
I don't seem to see it.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
Tom Widmer Guest
|
Posted: Fri Feb 24, 2006 3:49 am Post subject: Re: Template deduction fails, except when it succeeds |
|
|
Maciej Sobczak wrote:
| Quote: | typedef int array_of_int[5];
typedef int const array_of_const_int[5];
void foo(array_of_const_int &) {}
void bar(
int main()
{
array_of_int a = {1, 2, 3, 4, 5};
array_of_const_int &ca = a; // OK
foo(a); // OK
}
The above works fine (Comeau, g++), so the compiler is able to bind a
reference to an array of const given an array of non-const.
I'm asking what prevents it from deducing the type when templates are
involved. It's not the lack of conversion.
|
14.8.2.1/3 denotes the cases when the deduced type can differ from the
argument type (after the tranformations in 14.8.2/2 have been applied).
Pointers are allowed to require cv qualification adjustment (bullet 2)
but non-pointers aren't.
Tom
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|