Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > problem with partial ordering of classes

Reply
Thread Tools

problem with partial ordering of classes

 
 
Rodolfo Lima
Guest
Posts: n/a
 
      07-25-2010
Hi, I'm having some problems with the following code, gcc-4.5 refuses
to compile it:

#include <iostream>

template <bool B, class V=void> struct enable_if {};
template <class V> struct enable_if<true,V> { typedef V type; };

template <class T>
struct bar {};

template <class T, int ID, class V=void>
struct foo;

template<template<class> class V, class T, int ID>
struct foo<V<T>, ID>
{
static const int value = 1;
};

template<class T, int ID>
struct foo<bar<T>,ID, typename enable_if<ID!=0>::type>
{
static const int value = 2;
};

int main()
{
std::cout << foo<bar<int>,1>::value << std::endl;
}

//------------------------------------------


The error message:
teste.cpp: In function ‘int main()’:
teste.cpp:26:30: error: ambiguous class template instantiation for
‘struct foo<bar<int>, 1>’
teste.cpp:14:1: error: candidates are: struct foo<V<T>, ID>
teste.cpp:20:1: error: struct foo<bar<T>, ID, typename
enable_if<(ID != 0)>::type>
teste.cpp:26:15: error: incomplete type ‘foo<bar<int>, 1>’ used in
nested name specifier

According to partial ordering rules, struct foo<bar<T>,ID, typename
enable_if<ID!=0>::type> is more specialized than struct foo<V<T>, ID>,
isn't it? So it should be used, instead of giving an ambiguity error.

Am I wrong or is the compiler?

Regards,
Rodolfo Lima
 
Reply With Quote
 
 
 
 
Paul Bibbings
Guest
Posts: n/a
 
      07-25-2010
Rodolfo Lima <(E-Mail Removed)> writes:

> Hi, I'm having some problems with the following code, gcc-4.5 refuses
> to compile it:
>
> #include <iostream>
>
> template <bool B, class V=void> struct enable_if {};
> template <class V> struct enable_if<true,V> { typedef V type; };
>
> template <class T>
> struct bar {};
>
> template <class T, int ID, class V=void>
> struct foo;
>
> template<template<class> class V, class T, int ID>
> struct foo<V<T>, ID>
> {
> static const int value = 1;
> };
>
> template<class T, int ID>
> struct foo<bar<T>,ID, typename enable_if<ID!=0>::type>
> {
> static const int value = 2;
> };
>
> int main()
> {
> std::cout << foo<bar<int>,1>::value << std::endl;
> }
>
> //------------------------------------------
>
>
> The error message:
> teste.cpp: In function ¡®int main()¡¯:
> teste.cpp:26:30: error: ambiguous class template instantiation for
> ¡®struct foo<bar<int>, 1>¡¯
> teste.cpp:14:1: error: candidates are: struct foo<V<T>, ID>
> teste.cpp:20:1: error: struct foo<bar<T>, ID, typename
> enable_if<(ID != 0)>::type>
> teste.cpp:26:15: error: incomplete type ¡®foo<bar<int>, 1>¡¯ used in
> nested name specifier
>
> According to partial ordering rules, struct foo<bar<T>,ID, typename
> enable_if<ID!=0>::type> is more specialized than struct foo<V<T>, ID>,
> isn't it? So it should be used, instead of giving an ambiguity error.


This is interesting, and I only wish that I had the answer (which I
don't). What intrigues me, however, is that the rules of partial
ordering nevertheless are able to lead to a successful selection if your
first partial specialization of foo is likewise augmented to avoid
making use of the default template argument provided by the primary
template. That is, if we replace your:

template<template<class> class V, class T, int ID>
struct foo<V<T>, ID>
{
static const int value = 1;
};

with:

template<template<class> class V, class T, int ID>
struct foo<V<T>, ID, typename enable_if<ID!=0>::type>
{
static const int value = 1;
}

then your /second/ partial specialization, for which
foo<bar<int>,1>::value == 2, is selected as more specialized than the
first. (And note, that the code likewise works if *both*
specializations make use of this same default.) But then, what is going
on here? How is it that the viability of this second specialization as
preferred over the first thus augmented is suddenly undermined simply
when, as in your original code, this first is allowed to make use of the
default?

All that I can think of is that it might come down to an interpretation
of a note tucked away in [temp.deduct.type] ¡ì14.8.2.4/18:

"[Note: a default /template-argument/ cannot be specified in a function
template declaration or definition; therefore default
/template-argument/s cannot be used to influence template argument
deduction. ]"

which might be made to relate to the partial ordering of class template
partial specializations through the requirements of [temp.class.order]
¡ì14.5.4.2, for which the process involves the transformation of each
partial specialization into an appropriate function template, before
applying the rules of template argument deduction in the way
prescribed.

I have to admit that I have never fully followed through my
understanding (or lack of it) of the above-quoted note. However, it
looks almost as if gcc is taking this and saying something like "If
either both, or neither, of the partial specialization make use of the
default, then we can order this. However, if only one of them does then
that can be seen as an attempt to 'influence template argument
deduction' through use of a default template argument, and so we'll let
them both go, and leave it ambiguous." But that seems like nonsense,
and I can't believe that gcc is doing any such thing.

So. Like I said. Dunno!

Regards

Paul Bibbings
 
Reply With Quote
 
 
 
 
Paul Bibbings
Guest
Posts: n/a
 
      07-25-2010
Rodolfo Lima <(E-Mail Removed)> writes:

> Hi, I'm having some problems with the following code, gcc-4.5 refuses
> to compile it:
>
> #include <iostream>
>
> template <bool B, class V=void> struct enable_if {};
> template <class V> struct enable_if<true,V> { typedef V type; };
>
> template <class T>
> struct bar {};
>
> template <class T, int ID, class V=void>
> struct foo;
>
> template<template<class> class V, class T, int ID>
> struct foo<V<T>, ID>
> {
> static const int value = 1;
> };
>
> template<class T, int ID>
> struct foo<bar<T>,ID, typename enable_if<ID!=0>::type>
> {
> static const int value = 2;
> };
>
> int main()
> {
> std::cout << foo<bar<int>,1>::value << std::endl;
> }
>
> //------------------------------------------
>
>
> The error message:
> teste.cpp: In function ¡®int main()¡¯:
> teste.cpp:26:30: error: ambiguous class template instantiation for
> ¡®struct foo<bar<int>, 1>¡¯
> teste.cpp:14:1: error: candidates are: struct foo<V<T>, ID>
> teste.cpp:20:1: error: struct foo<bar<T>, ID, typename
> enable_if<(ID != 0)>::type>
> teste.cpp:26:15: error: incomplete type ¡®foo<bar<int>, 1>¡¯ used in
> nested name specifier
>
> According to partial ordering rules, struct foo<bar<T>,ID, typename
> enable_if<ID!=0>::type> is more specialized than struct foo<V<T>, ID>,
> isn't it? So it should be used, instead of giving an ambiguity error.


For the record, Comeau agrees with gcc-4.5 here:

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for
ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions

"ComeauTest.c", line 46: error: more than one partial specialization
matches the template argument list of class "foo<bar<int>, 1,
void>"
"foo<V<T>, ID, void>"
"foo<bar<T>, ID, enable_if<<expression>, void>::type>"
std::cout << foo<bar<int>,1>::value << std::endl;
^
1 error detected in the compilation of "ComeauTest.c".
In strict mode, with -tused, Compile failed
Hit the Back Button to review your code and compile options.
Compiled with C++0x extensions DISabled.

Regards

Paul Bibbings
 
Reply With Quote
 
Rodolfo Lima
Guest
Posts: n/a
 
      07-26-2010
It seems I was wrong after all.
See this thread:
http://groups.google.com/group/comp....9c5f5e5f6d0be/

In a nutshell (just for the record), the partial specialization

template<class T, int ID>
struct foo<bar<T>,ID, typename enable_if<ID!=0>::type>

can't be defined because the last argument falls into non-deducible
context (according to 14.8.2.4 [temp.deduct.type]). There's a core
issue about requiring this to be ill-formed.

[]s,
rod

PS: I really admire who understands/knows all of 14.8.2 [temp.deduct]
 
Reply With Quote
 
Paul Bibbings
Guest
Posts: n/a
 
      07-26-2010
On Jul 26, 2:45*am, Rodolfo Lima <(E-Mail Removed)> wrote:
> It seems I was wrong after all.
> See this thread:http://groups.google.com/group/comp....browse_frm/thr...
>
> In a nutshell (just for the record), the partial specialization
>
> template<class T, int ID>
> struct foo<bar<T>,ID, typename enable_if<ID!=0>::type>
>
> can't be defined because the last argument falls into non-deducible
> context (according to 14.8.2.4 [temp.deduct.type]). There's a core
> issue about requiring this to be ill-formed.
>
> []s,
> rod
>
> PS: I really admire who understands/knows all of 14.8.2 [temp.deduct]


I am not sure that I agree with this analysis, for essentially the
reasons that Johannes Schaub has tentatively added in his follow-up
post in c.l.c++.m. Note, as Johannes points out, that the last
argument
is not required to be a deduced-context, as ID is deduceable from the
second argument.

http://www.open-std.org/jtc1/sc22/wg...ctive.html#455 (as
referenced by Daniel Krugler) seems a much more likely avenue to
pursue
in understanding what's at issue here.

Regards

Paul Bibbings
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Z-Ordering (Morton ordering) question nbigaouette C Programming 2 11-06-2009 05:26 AM
Re: Partial 1.0 - Partial classes for Python Thomas Heller Python 13 02-08-2007 08:12 PM
Re: Partial 1.0 - Partial classes for Python J. Clifford Dyer Python 0 02-08-2007 05:29 PM
partial ordering of template functions & parameter specification Marek Vondrak C++ 9 05-15-2006 02:45 PM
partial ordering of overloaded function templates John Harrison C++ 5 06-09-2004 05:36 AM



Advertisments