函数模板重载 - 偏特化
Function template overloading - partial specialization
我有 2 个 class 遵循类似的模式:
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 编译得很好。另一方面,Bar
与上面的 Foo
具有相似的结构或模式;唯一的区别是它是静态的 getBar1()
、getBar2()
等不只是普通函数;它们是函数模板。
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... );
}
为什么当我开始添加一个 class 类型时,它是一个 class 模板;一切似乎都破裂了。上面的第一个 class 编译并 returns 返回适当的 Foo
。但是,在第二个 class Bar
中,我不断收到函数定义与现有声明不匹配的编译器错误。
这个问题与这里的这个问题相关:Specializing and or Overloading member function templates with variadic parameters
这个问题具体是关于为什么一个能编译而另一个不能。
The first class above compiles and returns back the appropriate Foo
是的,因为
template<>
foo1& Foo::getFoo( Param a, Param b, Param c ) {
return getFoo1( a, b, c );
}
它是模板方法的完整特化getFoo()
template<class FooType>
static FooType& getFoo( Param a, Param b, Param c );
FooType
类型固定为 foo1
。
并且您可以对模板函数(或方法)进行完全特化。
However, in the second class Bar
I keep getting compiler errors that function definition is not matching an existing declaration.
当然可以。
因为您正在尝试 部分 专门化模板方法 getBar()
template<typename Type, template<typename> class BarType, class... FuncParams>
static BarType<Type>& getBar( FuncParams... params );
将 BarType
固定为 bar1
template<typename Type, class... FuncParams>
bar1<Type>& Bar::getBar( FuncParams... params ) {
return {};//getBar1( params... );
}
但是您不能部分 专门化模板function/method。这是语言所禁止的。
如果你想要类似的东西,你必须通过结构的部分特化(或class)。
--- 编辑 ---
OP 问
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?
有很多方法可以使用结构的偏特化(classes)绕过 functions/methods 的 non-partial-specialization 限制。
在下面的基本示例中,我提出了一个带有模板 func()
方法的模板 foo
结构。 foo
的单个模板参数是 func()
返回的类型; func()
的可变模板类型列表是参数类型的列表。
但是你可以在不同的模式下玩这个游戏。
#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);
}
我有 2 个 class 遵循类似的模式:
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 编译得很好。另一方面,Bar
与上面的 Foo
具有相似的结构或模式;唯一的区别是它是静态的 getBar1()
、getBar2()
等不只是普通函数;它们是函数模板。
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... );
}
为什么当我开始添加一个 class 类型时,它是一个 class 模板;一切似乎都破裂了。上面的第一个 class 编译并 returns 返回适当的 Foo
。但是,在第二个 class Bar
中,我不断收到函数定义与现有声明不匹配的编译器错误。
这个问题与这里的这个问题相关:Specializing and or Overloading member function templates with variadic parameters
这个问题具体是关于为什么一个能编译而另一个不能。
The first class above compiles and returns back the appropriate
Foo
是的,因为
template<>
foo1& Foo::getFoo( Param a, Param b, Param c ) {
return getFoo1( a, b, c );
}
它是模板方法的完整特化getFoo()
template<class FooType>
static FooType& getFoo( Param a, Param b, Param c );
FooType
类型固定为 foo1
。
并且您可以对模板函数(或方法)进行完全特化。
However, in the second class
Bar
I keep getting compiler errors that function definition is not matching an existing declaration.
当然可以。
因为您正在尝试 部分 专门化模板方法 getBar()
template<typename Type, template<typename> class BarType, class... FuncParams>
static BarType<Type>& getBar( FuncParams... params );
将 BarType
固定为 bar1
template<typename Type, class... FuncParams>
bar1<Type>& Bar::getBar( FuncParams... params ) {
return {};//getBar1( params... );
}
但是您不能部分 专门化模板function/method。这是语言所禁止的。
如果你想要类似的东西,你必须通过结构的部分特化(或class)。
--- 编辑 ---
OP 问
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?
有很多方法可以使用结构的偏特化(classes)绕过 functions/methods 的 non-partial-specialization 限制。
在下面的基本示例中,我提出了一个带有模板 func()
方法的模板 foo
结构。 foo
的单个模板参数是 func()
返回的类型; func()
的可变模板类型列表是参数类型的列表。
但是你可以在不同的模式下玩这个游戏。
#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);
}