problem with partial ordering of classes

Discussion in 'C++' started by Rodolfo Lima, Jul 25, 2010.

  1. Rodolfo Lima

    Rodolfo Lima Guest

    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
     
    Rodolfo Lima, Jul 25, 2010
    #1
    1. Advertising

  2. Rodolfo Lima <> 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
     
    Paul Bibbings, Jul 25, 2010
    #2
    1. Advertising

  3. Rodolfo Lima <> 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
     
    Paul Bibbings, Jul 25, 2010
    #3
  4. Rodolfo Lima

    Rodolfo Lima Guest

    It seems I was wrong after all.
    See this thread:
    http://groups.google.com/group/comp.lang.c .moderated/browse_frm/thread/32d9c5f5e5f6d0be/

    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]
     
    Rodolfo Lima, Jul 26, 2010
    #4
  5. On Jul 26, 2:45 am, Rodolfo Lima <> wrote:
    > It seems I was wrong after all.
    > See this thread:http://groups.google.com/group/comp.lang.c .moderated/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/wg21/docs/cwg_active.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
     
    Paul Bibbings, Jul 26, 2010
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Harrison
    Replies:
    5
    Views:
    397
    John Harrison
    Jun 9, 2004
  2. Thomas Heller
    Replies:
    13
    Views:
    870
    Michele Simionato
    Feb 8, 2007
  3. J. Clifford Dyer

    Re: Partial 1.0 - Partial classes for Python

    J. Clifford Dyer, Feb 8, 2007, in forum: Python
    Replies:
    0
    Views:
    529
    J. Clifford Dyer
    Feb 8, 2007
  4. Marek Vondrak
    Replies:
    9
    Views:
    332
    Marek Vondrak
    May 15, 2006
  5. nbigaouette

    Z-Ordering (Morton ordering) question

    nbigaouette, Nov 5, 2009, in forum: C Programming
    Replies:
    2
    Views:
    2,178
Loading...

Share This Page