I have 2 classes that follow a similar pattern:
Foo.h
// header guard here
class Foo {
public:
Foo() = delete;
static foo1& getFoo1( Param a, Param b, Param c ) {
// code...
}
static foo2& getFoo2( Param a, Param b, Param c ) {
// code...
}
// generic function to return appropriate Foo Type based on template argument
template<class FooType>
static FooType& getFoo( Param a, Param b, Param c );
};
#endif
Foo.cpp
#include <Foo.h>
// specializations of getFoo() for each type
template<>
foo1& Foo::getFoo( Param a, Param b, Param c ) {
return getFoo1( a, b, c );
}
template<>
foo2& Foo::getFoo( Param a, Param b, Param c ) {
return getFoo2( a, b, c );
}
Foo above compiles just fine. Bar
on the other hand has a similar structure or pattern as Foo
above; the only difference is that it's static getBar1()
, getBar2()
etc. are not just normal functions; they are function templates.
Bar.h
// header guard
class Bar {
public:
Bar() = delete;
template<class IntType = int>
static bar1<IntType>& getBar1( IntType a, IntType b ) {
// code...
}
template<class RealType = double>
static bar2<RealType>& getBar2( RealType a, RealType b ) {
// code...
}
template<class IntType = int>
static bar3<IntType>& getBar3( IntType a ) {
// code...
}
template<class RealType = double>
static bar4<RealType>& getBar4( RealType a ) {
// code...
}
// ...
template<class RealType = double>
static bar12<RealType>& getBar12() {
// code...
}
template<class RealType = double, class A, class B>
static bar12&<RealType>& getBar12( A a1, A a2, B b1 ) {
// code...
}
template<class RealType = double, class X>
static bar12&<RealType>& getBar12( std::initialize_list<double> list, X x ) {
// code...
}
template<class RealType = double, class X>
static bar12&<RealType>& getBar12( std::size_t size, RealType a, RealType b, X x ) {
// code..
}
// Here is where I start to get into problems:
// I'm trying to do something similar to what I've done above in Foo for a generic function template.
template<typename Type, template<typename> class BarType, class... FuncParams>
static BarType<Type>& getBar( FuncParams... params );
};
#endif
Bar.cpp
#include "Bar.h"
// specializations of getBar() for each type
template<typename Type, class... FuncParams>
bar1<Type>& Bar::getBar( FuncParams... params ) {
return getBar1( params... );
}
template<typename Type, class... FuncParms>
bar2<Type>& Bar::getBar( FuncParams... params ) {
return getBar2( params... );
}
Why is it that when I begin to added a class type that is a class template; everything seems to break. The first class above compiles and returns back the appropriate Foo
. However, in the second class Bar
I keep getting compiler errors that function definition is not matching an existing declaration.
This question is related to this one here: Specializing and or Overloading member function templates with variadic parameters
This question is specifically about why the one does compile and the other one doesn't.
The first class above compiles and returns back the appropriate
Foo
Yes, because
template<>
foo1& Foo::getFoo( Param a, Param b, Param c ) {
return getFoo1( a, b, c );
}
it's a full specialization of the template method getFoo()
template<class FooType>
static FooType& getFoo( Param a, Param b, Param c );
with the FooType
type fixed to foo1
.
And you can make a full specialization of a template function (or method).
However, in the second class
Bar
I keep getting compiler errors that function definition is not matching an existing declaration.
Sure.
Because you're trying to partial specialize the template method getBar()
template<typename Type, template<typename> class BarType, class... FuncParams>
static BarType<Type>& getBar( FuncParams... params );
fixing BarType
to bar1
template<typename Type, class... FuncParams>
bar1<Type>& Bar::getBar( FuncParams... params ) {
return {};//getBar1( params... );
}
But you can't partial specialize a template function/method. It's forbidden by the language.
If you want something similar, you have to pass through the partial specialization of a struct (or class).
--- EDIT ---
The OP ask
You said, "you have to pass through the partial specialization of a struct( or class)." Okay; so there is a work around: would you be able to provide a small basic example?
There are many ways to use partial specialization of structs (classes) to bypass the non-partial-specialization limits for functions/methods.
In the following basic example I propose a template foo
struct with a template func()
method. The single template parameter for foo
is the type returned by func()
; the variadic template type list for func()
is the list of types of arguments.
But you can play this game in differents modes.
#include <iostream>
template <typename>
struct bar1
{ template <typename ... Args> bar1 (Args && ...) { } };
template <typename>
struct bar2
{ template <typename ... Args> bar2 (Args && ...) { } };
template <typename>
struct foo;
template <typename T>
struct foo<bar1<T>>
{
template <typename ... Args>
static bar1<T> func (Args && ... as)
{ return { std::forward<Args>(as)... }; }
};
template <typename T>
struct foo<bar2<T>>
{
template <typename ... Args>
static bar2<T> func (Args && ... as)
{ return { std::forward<Args>(as)... }; }
};
int main()
{
foo<bar1<int>>::func(1, "two", 3.0);
foo<bar2<long>>::func(4.0f, "five", 6L);
}