Problem with overloading function templates

Discussion in 'C++' started by Hendrik Schober, Apr 30, 2004.

  1. Hi,

    I have a problem, that boils down to the following code:

    #include <iostream>
    #include <typeinfo>

    class Test1 {};
    class Test2 {};
    class Test3 {};

    template< typename T >
    struct Cont { T t; };

    template< typename T >
    class TT { public: TT(T) {} };

    struct X {

    template< template<typename> class TT, typename T >
    static void f(const T& t)
    {
    std::cout << '\t' << typeid(t).name() << std::endl;
    }

    template< template<typename> class TT >
    static void f(const Test3& t)
    {
    std::cout << '\t' << typeid(t).name() << std::endl;
    }

    template< template<typename> class TT, typename T >
    static void f(const Cont<T>& c)
    {
    f<TT>( c.t ); // <== error here
    }

    };

    int main()
    {
    Cont<Test1> c1;
    Cont<Test2> c2;
    Cont<Test3> c3;

    X::f< TT, Test1 >(c1);
    X::f< TT, Test2 >(c2);
    X::f< TT, Test3 >(c3);

    return 0;
    }

    For this Comeau and CW9 report (in the line marked
    "error here") that the call is ambigous. (VC7.1
    accepts the code, BTW.)
    First, I don't see what's wrong, but overloading
    rules, especially in conjunctions with templates,
    are too complicated for me to remember them anyway.
    Second, I need a solution. I'm sure I would get it
    to work if I would use a class template and partial
    specialize it. However, the original code is long
    and complex enough without yet another helper class
    template...
    I would hope that, once the problem is known, a
    simpler way could be found. AFAIK, function template
    overloading _is_ possible, after all.

    TIA,

    Schobi

    --
    is never read
    I'm Schobi at suespammers dot org

    "Sometimes compilers are so much more reasonable than people."
    Scott Meyers
     
    Hendrik Schober, Apr 30, 2004
    #1
    1. Advertising

  2. Hendrik Schober

    Leor Zolman Guest

    On Fri, 30 Apr 2004 16:28:28 +0200, "Hendrik Schober" <>
    wrote:

    >Hi,
    >
    >I have a problem, that boils down to the following code:
    >
    > #include <iostream>
    > #include <typeinfo>
    >
    > class Test1 {};
    > class Test2 {};
    > class Test3 {};
    >
    > template< typename T >
    > struct Cont { T t; };
    >
    > template< typename T >
    > class TT { public: TT(T) {} };
    >
    > struct X {
    >
    > template< template<typename> class TT, typename T >
    > static void f(const T& t)
    > {
    > std::cout << '\t' << typeid(t).name() << std::endl;
    > }
    >
    > template< template<typename> class TT >
    > static void f(const Test3& t)
    > {
    > std::cout << '\t' << typeid(t).name() << std::endl;
    > }
    >
    > template< template<typename> class TT, typename T >
    > static void f(const Cont<T>& c)
    > {
    > f<TT>( c.t ); // <== error here
    > }
    >
    > };
    >
    > int main()
    > {
    > Cont<Test1> c1;
    > Cont<Test2> c2;
    > Cont<Test3> c3;
    >
    > X::f< TT, Test1 >(c1);
    > X::f< TT, Test2 >(c2);
    > X::f< TT, Test3 >(c3);
    >
    > return 0;
    > }
    >
    >For this Comeau and CW9 report (in the line marked
    >"error here") that the call is ambigous. (VC7.1
    >accepts the code, BTW.)
    >First, I don't see what's wrong, but overloading
    >rules, especially in conjunctions with templates,
    >are too complicated for me to remember them anyway.
    >Second, I need a solution. I'm sure I would get it
    >to work if I would use a class template and partial
    >specialize it. However, the original code is long
    >and complex enough without yet another helper class
    >template...
    >I would hope that, once the problem is known, a
    >simpler way could be found. AFAIK, function template
    >overloading _is_ possible, after all.


    Perhaps you've OVER-simplified, because it is not clear to my why you have
    the template-template parameter there in your templates. I'm not sure, but
    if it were used perhaps there might be more of a handle to be had on how to
    disambiguate your calls. If you don't really need that
    template-template-parameter, then your class can just be this:

    struct X {

    // template< template<typename> class TT, typename T >
    template<typename T >
    static void f(const T& t)
    {
    std::cout << '\t' << typeid(t).name() << std::endl;
    }


    // template< template<typename> class TT >
    static void f(const Test3& t)
    {
    std::cout << '\t' << typeid(t).name() << std::endl;
    }

    template< template<typename> class TT, typename T >
    static void f(const Cont<T>& c)
    {
    f( c.t ); // <== error here
    }

    };

    -leor

    >
    >TIA,
    >
    >Schobi


    --
    Leor Zolman --- BD Software --- www.bdsoft.com
    On-Site Training in C/C++, Java, Perl and Unix
    C++ users: download BD Software's free STL Error Message Decryptor at:
    www.bdsoft.com/tools/stlfilt.html
     
    Leor Zolman, Apr 30, 2004
    #2
    1. Advertising

  3. Leor Zolman <> wrote:
    > [...]
    > Perhaps you've OVER-simplified, because it is not clear to my why you have
    > the template-template parameter there in your templates.


    Yes, that's due to the simplification.
    In the real code, the template template
    arg is used to pick some algorithms that
    are to be applied. They are vital to
    these functions. :(

    > I'm not sure, but
    > if it were used perhaps there might be more of a handle to be had on how to
    > disambiguate your calls. If you don't really need that
    > template-template-parameter, then your class can just be this:
    >
    > struct X {
    >
    > // template< template<typename> class TT, typename T >
    > template<typename T >
    > static void f(const T& t)
    > {
    > std::cout << '\t' << typeid(t).name() << std::endl;
    > }
    >
    >
    > // template< template<typename> class TT >
    > static void f(const Test3& t)
    > {
    > std::cout << '\t' << typeid(t).name() << std::endl;
    > }
    >
    > template< template<typename> class TT, typename T >
    > static void f(const Cont<T>& c)
    > {
    > f( c.t ); // <== error here
    > }
    >
    > };


    I am surprised. Why would the other template arg
    cause the call to be ambiguos?

    > -leor


    Schobi

    --
    is never read
    I'm Schobi at suespammers dot org

    "Sometimes compilers are so much more reasonable than people."
    Scott Meyers
     
    Hendrik Schober, Apr 30, 2004
    #3
  4. Hendrik Schober

    Leor Zolman Guest

    On Fri, 30 Apr 2004 16:53:59 +0200, "Hendrik Schober" <>
    wrote:

    >
    >> I'm not sure, but
    >> if it were used perhaps there might be more of a handle to be had on how to
    >> disambiguate your calls. If you don't really need that
    >> template-template-parameter, then your class can just be this:
    >>
    >> struct X {
    >>
    >> // template< template<typename> class TT, typename T >
    >> template<typename T >
    >> static void f(const T& t)
    >> {
    >> std::cout << '\t' << typeid(t).name() << std::endl;
    >> }
    >>
    >>
    >> // template< template<typename> class TT >
    >> static void f(const Test3& t)
    >> {
    >> std::cout << '\t' << typeid(t).name() << std::endl;
    >> }
    >>
    >> template< template<typename> class TT, typename T >
    >> static void f(const Cont<T>& c)
    >> {
    >> f( c.t ); // <== error here
    >> }
    >>
    >> };

    >
    > I am surprised. Why would the other template arg
    > cause the call to be ambiguos?


    Because in my simplified version, that second version of f is not a
    template.
    -leor

    >
    >> -leor

    >
    > Schobi


    --
    Leor Zolman --- BD Software --- www.bdsoft.com
    On-Site Training in C/C++, Java, Perl and Unix
    C++ users: download BD Software's free STL Error Message Decryptor at:
    www.bdsoft.com/tools/stlfilt.html
     
    Leor Zolman, Apr 30, 2004
    #4
  5. Leor Zolman <> wrote:
    > [...]
    > Because in my simplified version, that second version of f is not a
    > template.


    <ahem>
    Right. Sorry for that stupid question.

    > -leor


    Schobi

    --
    is never read
    I'm Schobi at suespammers dot org

    "Sometimes compilers are so much more reasonable than people."
    Scott Meyers
     
    Hendrik Schober, Apr 30, 2004
    #5
  6. Hendrik Schober wrote in news:c6tkr6$7ve$ in
    comp.lang.c++:

    > Hi,
    >
    > I have a problem, that boils down to the following code:
    >
    > #include <iostream>
    > #include <typeinfo>
    >
    > class Test1 {};
    > class Test2 {};
    > class Test3 {};
    >
    > template< typename T >
    > struct Cont { T t; };
    >
    > template< typename T >
    > class TT { public: TT(T) {} };
    >
    > struct X {
    >
    > template< template<typename> class TT, typename T >
    > static void f(const T& t)
    > {
    > std::cout << '\t' << typeid(t).name() << std::endl;
    > }
    >


    Here's a Hack-around:

    template< template<typename> class TT, typename T >
    static void f(const volatile T& tv)
    {
    T const &t = const_cast< T const & >( tv );
    std::cout << '\t' << typeid(t).name() << std::endl;
    }

    > template< template<typename> class TT >
    > static void f(const Test3& t)
    > {
    > std::cout << '\t' << typeid(t).name() << std::endl;
    > }
    >
    > template< template<typename> class TT, typename T >
    > static void f(const Cont<T>& c)
    > {
    > f<TT>( c.t ); // <== error here
    > }
    >
    > };
    >
    > int main()
    > {
    > Cont<Test1> c1;
    > Cont<Test2> c2;
    > Cont<Test3> c3;
    >
    > X::f< TT, Test1 >(c1);
    > X::f< TT, Test2 >(c2);
    > X::f< TT, Test3 >(c3);
    >
    > return 0;
    > }
    >
    > For this Comeau and CW9 report (in the line marked
    > "error here") that the call is ambigous. (VC7.1
    > accepts the code, BTW.)


    Neither is a better match (they're both exact) and neither is more
    specialized, and since there is no such thing as a function partial
    specailization, we can't make it so.

    > First, I don't see what's wrong, but overloading
    > rules, especially in conjunctions with templates,
    > are too complicated for me to remember them anyway.
    > Second, I need a solution. I'm sure I would get it
    > to work if I would use a class template and partial
    > specialize it. However, the original code is long
    > and complex enough without yet another helper class
    > template...
    > I would hope that, once the problem is known, a
    > simpler way could be found. AFAIK, function template
    > overloading _is_ possible, after all.
    >


    I Think Comeau/CW (also g++ 3.2 & 3.4 pre-release) is correct here.
    Though I wouldn't bet my shirt on it.

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
     
    Rob Williscroft, Apr 30, 2004
    #6
  7. Rob Williscroft <> wrote:
    > [...]
    > Here's a Hack-around:
    >
    > template< template<typename> class TT, typename T >
    > static void f(const volatile T& tv)
    > {
    > T const &t = const_cast< T const & >( tv );
    > std::cout << '\t' << typeid(t).name() << std::endl;
    > }


    Ugh.

    > [...]
    >
    > Neither is a better match (they're both exact) and neither is more
    > specialized,


    I always thought a types always is a
    better match than a template arg?
    Well, I guess I'm wrong...

    > and since there is no such thing as a function partial
    > specailization, we can't make it so.



    I was afraid I'd have to create a helper
    class template.

    > [...]
    > Rob.



    Thanks,

    Schobi

    --
    is never read
    I'm Schobi at suespammers dot org

    "Sometimes compilers are so much more reasonable than people."
    Scott Meyers
     
    Hendrik Schober, Apr 30, 2004
    #7
  8. Hendrik Schober <> wrote:
    > [...]


    Thanks to everybody who cared. I found this:

    template< template<typename> class TT, typename T >
    static void f(const T& t, CBool<false> /*isTest3*/)
    {
    std::cout << '\t' << typeid(t).name() << std::endl;
    }

    template< template<typename> class TT, typename T >
    static void f(const T& t, CBool<true> /*isTest3*/)
    {
    std::cout << '\t' << typeid(t).name() << std::endl;
    }

    template< template<typename> class TT, typename T >
    static void f(const Cont<T>& c)
    {
    f<TT>( c.t, CBool<CIsSameType<T,Test3>::result>() );
    }

    Comeau accepts it, so I assume it's OK...

    Schobi

    --
    is never read
    I'm Schobi at suespammers dot org

    "Sometimes compilers are so much more reasonable than people."
    Scott Meyers
     
    Hendrik Schober, Apr 30, 2004
    #8
    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. JKop
    Replies:
    3
    Views:
    479
  2. Iyer, Prasad C

    Overloading __init__ & Function overloading

    Iyer, Prasad C, Sep 30, 2005, in forum: Python
    Replies:
    3
    Views:
    6,414
    Fredrik Lundh
    Sep 30, 2005
  3. WittyGuy
    Replies:
    16
    Views:
    3,839
  4. recover
    Replies:
    2
    Views:
    813
    recover
    Jul 25, 2006
  5. Replies:
    1
    Views:
    319
Loading...

Share This Page