469,568 Members | 1,441 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,568 developers. It's quick & easy.

Problem with overloading function templates

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

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Jul 22 '05 #1
7 1787
On Fri, 30 Apr 2004 16:28:28 +0200, "Hendrik Schober" <Sp******@gmx.de>
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
Jul 22 '05 #2
Leor Zolman <le**@bdsoft.com> 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

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Jul 22 '05 #3
On Fri, 30 Apr 2004 16:53:59 +0200, "Hendrik Schober" <Sp******@gmx.de>
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
Jul 22 '05 #4
Leor Zolman <le**@bdsoft.com> wrote:
[...]
Because in my simplified version, that second version of f is not a
template.
<ahem>
Right. Sorry for that stupid question.
-leor


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Jul 22 '05 #5
Hendrik Schober wrote in news:c6**********@news1.transmedia.de 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/
Jul 22 '05 #6
Rob Williscroft <rt*@freenet.co.uk> 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

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers

Jul 22 '05 #7
Hendrik Schober <Sp******@gmx.de> 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

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
Jul 22 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

17 posts views Thread by Terje Slettebų | last post: by
4 posts views Thread by Dave Theese | last post: by
4 posts views Thread by Leslaw Bieniasz | last post: by
2 posts views Thread by franklini | last post: by
39 posts views Thread by zeus | last post: by
15 posts views Thread by iu2 | last post: by
4 posts views Thread by guiromero | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.