I have a feeling that I can come up with a much better title for this thread once I know the answer to this question :).

Say I have a function template template <typename T> void MyFunction(). Now I want to specialize MyFunction for a templated type. That is, say I have template <typename C> class MyClass{}; Now I want to specialize MyFunction for any MyClass<C> that was passed as the template parameter to MyFunction. Is this possible?

The structure would be something like this:

#include <iostream>
#include <vector>
 
#include "Point.h"
 
template <typename C>
class MyClass
{
};
 
template <typename T>
void Output(const T& object)
{
  std::cout << object << std::endl;
}
 
// I want this to handle MyClass<int>, MyClass<float>, MyClass<anything>
template <>
void Output<MyClass<C> >(const MyClass<C>& object)
{
  std::cout << "unsigned int " << object << std::endl;
}
 
int main(int argc, char* argv[])
{
  MyClass<double> myClass;
  Output(myClass);
 
  Output(2u);
 
  return 0;
}

Any ideas?

Thanks,

David

Recommended Answers

All 9 Replies

This would suffice:

template< typename T > void foo( const T& t ) ;

template< typename T > void foo( const MyClass<T>& mc ) ;

The partial ordering of templates involved (that is taken into account in the deduction process) would make the second template be preferred over the first for objects of type MyClass<T>.

commented: Thanks for several very helpful answers! +12

Hm, I thought that was what I wanted, but that requires the POD type (inner template parameter) to be passed implicitly. What about this:

#include <iostream>
#include <vector>

template <typename T>
void Output(const T& object)
{
  std::cout << object << std::endl;
}

template <typename C>
class MyClass
{
};

// Handles MyClass<int>, MyClass<float>, MyClass<anything>
template <typename T>
void Output( const MyClass<T>& object)
{
  std::cout << "Special " << std::endl;
}

int main(int argc, char* argv[])
{
  MyClass<double> myClass;
  //Output(myClass);
  Output<MyClass<double> >(myClass);

  Output(2u);

  return 0;
}

Here the type of the argument is explicitly stated, and it doesn't work (I think it tries to instantiate with MyClass<MyClass<double> >.

I need this because I am actually trying to overload a function inside of a class:

#include <iostream>
#include <vector>

template <typename T>
class Simple
{
};

template <typename T>
class MyClass
{
public:

  void Output(const T& object)
  {
    std::cout << "NON-MyClass" << std::endl;
  }

  // I want this to handle MyClass<int>, MyClass<float>, MyClass<anything>
  void Output( const MyClass<T>& object)
  {
    std::cout << "MyClass" << std::endl;
  }
};


int main(int argc, char* argv[])
{
  MyClass<double> myClass;
  myClass.Output(2.0f);

  Simple<int> mySimple;
  MyClass<Simple<int> > myClass2;
  myClass2.Output(mySimple);

  return 0;
}

Thoughts?

David

Why do you want to specify the template parameters explicitly?
I'm not really sure I understood what you want, so I'll just list a
couple of things hoping one or two of them suits your needs.

#include <iostream>
#include <vector>

template <class T> class Simple { };

template <class T>
class MyClass
{
public:

    template <class U>
    void Output(const U & object)
    { std::cout << "any_type" << std::endl; }

    void Output(const T & object)
    { std::cout << "just T" << std::endl; }

    void Output(const MyClass<T> & object)
    { std::cout << "MyClass < T >" << std::endl; }

    template <class U>
    void Output(const MyClass<U> & object)
    { std::cout << "MyClass < any_type >" << std::endl; }

    template <template <class> class U>
    void Output(const U<T> & object)
    { std::cout << "any_type < T >" << std::endl; }

    template <template <class> class U>
    void Output(const MyClass<U<T> > & object)
    { std::cout << "MyClass< any_type < T > >" << std::endl; }

    template <template <class> class U, class V>
    void Output(const U<V> & object)
    { std::cout << "any_type < any_type >" << std::endl; }

    template <template <class> class U, class V>
    void Output(const MyClass<U<V> > & object)
    { std::cout << "MyClass< any_type < any_type > >" << std::endl; }
};

int main()
{
    MyClass<char> my_class_c;
    MyClass<int>  my_class_i;

    Simple<char> simple_c;
    Simple<int>  simple_i;

    my_class_i.Output(0);
    my_class_i.Output('0');

    std::cout << std::endl;

    my_class_i.Output(simple_i);
    my_class_i.Output(simple_c);

    std::cout << std::endl;

    my_class_i.Output(my_class_i);
    my_class_i.Output(my_class_c);

    std::cout << std::endl;

    MyClass<Simple<int> > my_class_si;

    my_class_i.Output(my_class_si);
    my_class_c.Output(my_class_si);
}

EDIT: Added one more case.

I am not familiar with this syntax, but I think it may be what I want:

template <template <class> class U>

Is this called something that I can go look up?

Yes. Look up template template parameters.

Very cool, thanks!

Interesting, it seems that 'class' and 'typename' differ in template template parameters:

template <template <typename> class T>
vs
template <template <typename> typename T> // doesn't work

I thought they were synonymous. I guess I was wrong!

> Hm, I thought that was what I wanted, but that requires the POD type (inner template parameter) to be passed implicitly.
> What about this:

In the function (btw, it is an overload, not a specialization)

// Handles MyClass<int>, MyClass<float>, MyClass<anything>
template <typename T>
void Output( const MyClass<T>& object)
{
  std::cout << "Special " << std::endl;
}

The type of object is (a reference to const) MyClass<T> And the template parameter is T (not MyClass<T>).

int main()
{
  MyClass<double> myClass;
  
  // void Output( const MyClass<T>& object) selected by deduction with partial ordering
  Output(myClass) ; 
  
  // error: T is explicitly specified to be MyClass<double>. Therefore, asks for
  // an instantiation of the template with an argument of type MyClass< MyClass<double> >
  Output<MyClass<double> >(myClass);
  
  // fine: T is explicitly specified to be double, type of myClass is MyClass<double>
  // void Output( const MyClass<T>& object) selected by partial ordering
  Output<double>(myClass) ; 
}

I thought I would have to specify it explicitly because in my real case the function parameter was actually a template parameter of the class that the function is inside of. But I think it is working properly automatically deducing it, thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.