Let's suppose to have a template
class 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.
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.
The question on SO does not explain how to specialise with a template argument. Indeed, my question shows how the compiler complains about that.
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.
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.)
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 arguments be used with the template class? Explanation: The template class can use default arguments.
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 Sorry: my idea doesn't works because this method require the use of default template arguments for methods that is a C++11 innovation.std::enable_if
but you can simulate it (give me some minutes and I try to propose an example).
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With