Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template Specialisation with Template Argument

Let's suppose to have a templateclass Foo:

template <typename T>
class Foo {
  void foo();
};

I have another template class Bar (independent from the first one):

template <int N>
class Bar {};

Let's say, I want to specialise the foo() method for whatever Bar class. I'd wrongly write:

template <>
template <int N>
void Foo<Bar<N> >::foo() { /* ... */ }

The compiler blames me for because the type is not complete:

error: invalid use of incomplete type 'class Foo<Bar<N> >'
 void Foo<Bar<N> >::foo() { }

Code

I am using C++98, but I'd like to know if there exist different solutions in C++11.


Note

I could solve the problem specialising the entire class Foo for a generic Bar, but after I should have to define all methods.

Example Code

That's not what I want, I am looking for (if exists) more elegant solution (both C++98 and C++11) which allows me to specialise and implement only a single class method.


EDIT:

The question on SO does not explain how to specialise with a template argument. Indeed, my question shows how the compiler complains about that.

like image 460
BiagioF Avatar asked Nov 07 '17 15:11

BiagioF


People also ask

What is a template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

What is a template argument?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Can default argument be used with the template class?

Can default arguments be used with the template class? Explanation: The template class can use default arguments.


1 Answers

For C++11 you can SFINAE enable/disable (using std::enable_if) two differents versions of foo() inside a not specialized Foo class.

In C++98 you don't have std::enable_if but you can simulate it (give me some minutes and I try to propose an example). Sorry: my idea doesn't works because this method require the use of default template arguments for methods that is a C++11 innovation.

Another way is define a template base class for Foo(), say FooBase, insert foo() (and only foo()) in FooBase and specialize FooBase.

Another way, that works also with C++98, can be tag dispatching: you can define an unique foo(), with zero parameter, that call another foo(), with a parameter that is determined by T.

The following is a full (C++98 compilable) example

#include <iostream>

struct barWay   {};
struct noBarWay {};

template <int>
struct Bar
 { };

template <typename>
struct selectType
 { typedef noBarWay type; };

template <int N>
struct selectType< Bar<N> >
 { typedef barWay type; };

template <typename T>
struct Foo
 {
   void foo (noBarWay const &)
    { std::cout << "not Bar version" << std::endl; }

   void foo (barWay const &)
    { std::cout << "Bar version" << std::endl; }

   void foo ()
    { foo(typename selectType<T>::type()); }
 };


int main ()
 {
   Foo<int>        fi;
   Foo< Bar<42> >  fb;

   fi.foo();
   fb.foo(); 
 }
like image 166
max66 Avatar answered Oct 18 '22 03:10

max66