public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/59056] New: enable_if turns a non-ambiguous template into an ambiguous one
@ 2013-11-08 22:19 walter.mascarenhas at gmail dot com
  2013-11-08 22:35 ` [Bug c++/59056] " paolo.carlini at oracle dot com
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: walter.mascarenhas at gmail dot com @ 2013-11-08 22:19 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59056

            Bug ID: 59056
           Summary: enable_if turns a non-ambiguous template into an
                    ambiguous one
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: walter.mascarenhas at gmail dot com

Created attachment 31187
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=31187&action=edit
a simple code illustrating the bug

The attached file shows that by turning a specialization of

template <class A, class Enable = void>
struct Foo {};

like this one (which works just fine)

template <class A>
struct Foo<A, void>{};

into 

template <class A>
struct Foo<A, std::enable_if< typename always_true<A>() >::type >{};

we can get ambigouities, even when typename always_true<A>() >::type
always resolves to void.

For more details, look at the attachement


^ 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 ` 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

end of thread, other threads:[~2013-11-14 10:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).