* [Bug c++/59056] enable_if turns a non-ambiguous template into an ambiguous one
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
@ 2013-11-08 22:35 ` paolo.carlini at oracle dot com
2013-11-09 12:58 ` redi at gcc dot gnu.org
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: paolo.carlini at oracle dot com @ 2013-11-08 22:35 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
--- Comment #1 from Paolo Carlini <paolo.carlini at oracle dot com> ---
Needs an analysis, but I doubt this is a bug, all the up to date compilers I
have handy (eg, clang, icc) reject it the same way.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] enable_if turns a non-ambiguous template into an ambiguous one
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
2013-11-08 22:35 ` [Bug c++/59056] " paolo.carlini at oracle dot com
@ 2013-11-09 12:58 ` redi at gcc dot gnu.org
2013-11-11 11:37 ` redi at gcc dot gnu.org
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: redi at gcc dot gnu.org @ 2013-11-09 12:58 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I must be misunderstanding something, because rewriting the class template
partial specializations as function templates (as per [temp.class.order]) shows
that one is more specialized than the other, as the functions are not
ambiguous:
#include <type_traits>
template <class T> class Foo {};
template <class X>
constexpr bool check()
{
return true;
}
template <class X, class Enable = void>
struct Bar {};
template<class X>
void func(Bar<X, typename std::enable_if< check<X>() >::type>) { }
template<class T>
int func(Bar<Foo<T>>) { return 0; }
void instance()
{
Bar< Foo<int> > av;
int i = func(av);
}
I thought if the partial specializations were ambiguous then these function
overloads should be too.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] enable_if turns a non-ambiguous template into an ambiguous one
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
2013-11-08 22:35 ` [Bug c++/59056] " paolo.carlini at oracle dot com
2013-11-09 12:58 ` redi at gcc dot gnu.org
@ 2013-11-11 11:37 ` redi at gcc dot gnu.org
2013-11-13 11:11 ` paolo.carlini at oracle dot com
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: redi at gcc dot gnu.org @ 2013-11-11 11:37 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Similar (but not identical) to PR 58752
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] enable_if turns a non-ambiguous template into an ambiguous one
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
` (2 preceding siblings ...)
2013-11-11 11:37 ` redi at gcc dot gnu.org
@ 2013-11-13 11:11 ` paolo.carlini at oracle dot com
2013-11-13 21:00 ` richard-gccbugzilla at metafoo dot co.uk
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: paolo.carlini at oracle dot com @ 2013-11-13 11:11 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
Paolo Carlini <paolo.carlini at oracle dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |richard-gccbugzilla@metafoo
| |.co.uk
--- Comment #4 from Paolo Carlini <paolo.carlini at oracle dot com> ---
Maybe we can ask Richard's opinion about this one too.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] enable_if turns a non-ambiguous template into an ambiguous one
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
` (3 preceding siblings ...)
2013-11-13 11:11 ` paolo.carlini at oracle dot com
@ 2013-11-13 21:00 ` richard-gccbugzilla at metafoo dot co.uk
2013-11-13 23:16 ` [Bug c++/59056] ambiguous call to function templates overloads not diagnosed redi at gcc dot gnu.org
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: richard-gccbugzilla at metafoo dot co.uk @ 2013-11-13 21:00 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
--- Comment #5 from Richard Smith <richard-gccbugzilla at metafoo dot co.uk> ---
(In reply to Jonathan Wakely from comment #2)
> I thought if the partial specializations were ambiguous then these function
> overloads should be too.
Yes, this inconsistency is very surprising. GCC, EDG, and Clang all behave the
same way, and yet I can find no justification for this behavior in the
standard.
Morally, the function call should be ambiguous. The first 'func' takes Bar<X>
for any X where check<X>() is true, and the second 'func' takes Bar<X> for any
X that matches Foo<T>. Neither of those constraints implies the other, so the
call should be ambiguous.
In Clang's case, the problem is that we fail to enforce
[temp.deduct.type](14.8.2.5)/1 when partially ordering function templates -- we
don't check that deduction actually succeeded in finding types that make 'A'
match the 'deduced A' -- but we do check that when partially ordering class
templates, and we don't spot the problem earlier because the enable_if<...> is
a non-deduced context. I expect EDG and GCC have a similar bug.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] ambiguous call to function templates overloads not diagnosed
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
` (4 preceding siblings ...)
2013-11-13 21:00 ` richard-gccbugzilla at metafoo dot co.uk
@ 2013-11-13 23:16 ` redi at gcc dot gnu.org
2013-11-14 2:26 ` [Bug c++/59056] ambiguous call to function template " walter.mascarenhas at gmail dot com
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: redi at gcc dot gnu.org @ 2013-11-13 23:16 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords| |accepts-invalid
Status|UNCONFIRMED |NEW
Last reconfirmed| |2013-11-13
Summary|enable_if turns a |ambiguous call to function
|non-ambiguous template into |templates overloads not
|an ambiguous one |diagnosed
Ever confirmed|0 |1
--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Thanks, Richard. So the original testcase is correctly rejected as ambiguous,
but G++ has an accepts-invalid bug for the code in comment 2.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] ambiguous call to function template overloads not diagnosed
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
` (5 preceding siblings ...)
2013-11-13 23:16 ` [Bug c++/59056] ambiguous call to function templates overloads not diagnosed redi at gcc dot gnu.org
@ 2013-11-14 2:26 ` walter.mascarenhas at gmail dot com
2013-11-14 3:04 ` richard-gccbugzilla at metafoo dot co.uk
2013-11-14 10:20 ` walter.mascarenhas at gmail dot com
8 siblings, 0 replies; 10+ messages in thread
From: walter.mascarenhas at gmail dot com @ 2013-11-14 2:26 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
--- Comment #7 from Walter Mascarenhas <walter.mascarenhas at gmail dot com> ---
In itself, Richard's paragraph "Morally, the function should ambiguous... "
implies that the code below is ambiguous. However, it
compiles just fine with gcc 4.8.1, because gcc also takes into
account the information that check< Foo<int> >() is false
in order to discard the specialization with the enable_if. In
other words, the X in check<X> is not completely arbitrary,
it my be related to Foo<T>.
I find it odd that in the code below gcc uses the information
that check< Foo<int> >() is false and in the first version it
neglects the equivalent information that check< Foo<int> >()
is true. Of course, the standard has the last word on these
things, but not everything in it is "morally" obvious or
completely logical.
Here is the modified code (I only changed the value
returned by check from true to false):
template <class X>
constexpr bool check() { return false; }
template <class X, class Enable = void> struct Bar {};
template <class X>
struct Bar<X, typename std::enable_if< check<X>() >::type> {};
template <class T>
struct Bar< Foo<T> > {};
void instance()
{
Bar< Foo<int>, void > av;
}
On Wed, Nov 13, 2013 at 7:00 PM, richard-gccbugzilla at metafoo dot co.uk <
gcc-bugzilla@gcc.gnu.org> wrote:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
>
> --- Comment #5 from Richard Smith <richard-gccbugzilla at metafoo dot
> co.uk> ---
> (In reply to Jonathan Wakely from comment #2)
> > I thought if the partial specializations were ambiguous then these
> function
> > overloads should be too.
>
> Yes, this inconsistency is very surprising. GCC, EDG, and Clang all behave
> the
> same way, and yet I can find no justification for this behavior in the
> standard.
>
> Morally, the function call should be ambiguous. The first 'func' takes
> Bar<X>
> for any X where check<X>() is true, and the second 'func' takes Bar<X> for
> any
> X that matches Foo<T>. Neither of those constraints implies the other, so
> the
> call should be ambiguous.
>
> In Clang's case, the problem is that we fail to enforce
> [temp.deduct.type](14.8.2.5)/1 when partially ordering function templates
> -- we
> don't check that deduction actually succeeded in finding types that make
> 'A'
> match the 'deduced A' -- but we do check that when partially ordering class
> templates, and we don't spot the problem earlier because the
> enable_if<...> is
> a non-deduced context. I expect EDG and GCC have a similar bug.
>
> --
> You are receiving this mail because:
> You reported the bug.
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] ambiguous call to function template overloads not diagnosed
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
` (6 preceding siblings ...)
2013-11-14 2:26 ` [Bug c++/59056] ambiguous call to function template " walter.mascarenhas at gmail dot com
@ 2013-11-14 3:04 ` richard-gccbugzilla at metafoo dot co.uk
2013-11-14 10:20 ` walter.mascarenhas at gmail dot com
8 siblings, 0 replies; 10+ messages in thread
From: richard-gccbugzilla at metafoo dot co.uk @ 2013-11-14 3:04 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
--- Comment #8 from Richard Smith <richard-gccbugzilla at metafoo dot co.uk> ---
(In reply to Walter Mascarenhas from comment #7)
> In itself, Richard's paragraph "Morally, the function should ambiguous... "
> implies that the code below is ambiguous. However, it
> compiles just fine with gcc 4.8.1, because gcc also takes into
> account the information that check< Foo<int> >() is false
> in order to discard the specialization with the enable_if. In
> other words, the X in check<X> is not completely arbitrary,
> it my be related to Foo<T>.
GCC can't instantiate check<Ty> with a dependent type Ty, because that's not a
meaningful thing to do. And it's not allowed to use Foo<int>, because partial
ordering of templates does not depend on the actual deduced arguments for the
template specialization (it orders the templates themselves, not their
specializations). Also, the only available definition of check always returns
true. So I really don't see how that could be the case.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Bug c++/59056] ambiguous call to function template overloads not diagnosed
2013-11-08 22:19 [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one walter.mascarenhas at gmail dot com
` (7 preceding siblings ...)
2013-11-14 3:04 ` richard-gccbugzilla at metafoo dot co.uk
@ 2013-11-14 10:20 ` walter.mascarenhas at gmail dot com
8 siblings, 0 replies; 10+ messages in thread
From: walter.mascarenhas at gmail dot com @ 2013-11-14 10:20 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
--- Comment #9 from Walter Mascarenhas <walter.mascarenhas at gmail dot com> ---
1) I just wrote that Richard's paragraph, IN ITSELF,
does not explain why things are as they are. I did not
write that there aren't other reasons to justify the
standard's decisions.
2) As I wrote, GCC does depend on the value of check< Foo<int> >()
in order to decide whether or not the code is ambiguous:
If we provide an specialization
template <> constexpr bool check<Foo<int> >() {return false;}
then the ambiguity goes away. Of course, this specialization
changes the code and brings in other issues. I just want
to point out, naively, that the value of
check< Foo<int> >() is relevant for GCC.
3) In my naive user point of view, I believed that Richard's
observation that "the only available definition of check
always return true" would imply that
template <class X> struct Bar<X, Enable_if< check<X>() > >{};
would be essentially equivalent to
template <class X> struct Bar<X, void>{};
and this looks less specialized than
template <> struct Bar< Foo<int>, void >{},
This was my naive view. If the standard says
otherwise then there is no point in arguing
about it.
walter.
On Thu, Nov 14, 2013 at 1:04 AM, richard-gccbugzilla at metafoo dot co.uk <
gcc-bugzilla@gcc.gnu.org> wrote:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056
>
> --- Comment #8 from Richard Smith <richard-gccbugzilla at metafoo dot
> co.uk> ---
> (In reply to Walter Mascarenhas from comment #7)
> > In itself, Richard's paragraph "Morally, the function should
> ambiguous... "
> > implies that the code below is ambiguous. However, it
> > compiles just fine with gcc 4.8.1, because gcc also takes into
> > account the information that check< Foo<int> >() is false
> > in order to discard the specialization with the enable_if. In
> > other words, the X in check<X> is not completely arbitrary,
> > it my be related to Foo<T>.
>
> GCC can't instantiate check<Ty> with a dependent type Ty, because that's
> not a
> meaningful thing to do. And it's not allowed to use Foo<int>, because
> partial
> ordering of templates does not depend on the actual deduced arguments for
> the
> template specialization (it orders the templates themselves, not their
> specializations). Also, the only available definition of check always
> returns
> true. So I really don't see how that could be the case.
>
> --
> You are receiving this mail because:
> You reported the bug.
>
^ permalink raw reply [flat|nested] 10+ messages in thread