[英]Specializing and or Overloading member function templates with variadic parameters
嘗試解決類成員的重載解決方案:靜態函數模板重載-部分專業化。
我目前有一個這樣聲明/定義的類:
注意:我對Param a
, Param b
, Param c
等的使用與實際的聲明/定義沒有直接關系。 例如,這些可以是傳遞給函數的任意類型:可以是int a
, enum b
, char c
。 我只是用它來顯示聲明的模式,但是所有不同的引擎都采用相同的3個不同的參數。
SomeEngine.h
#ifndef SOME_ENGINE_H
#define SOME_ENGINE_H
class SomeEngine {
public:
SomeEngine() = delete;
static engineA& getEngineA( Param a, Param b, Param c );
static engineB& getEngineB( Param a, Param b, Param c );
// ... more static functions to return other engines
template<class Engine>
static Engine& getEngine( Param a, Param b, Param c );
};
// Another class
// function template that uses both classes above
#endif // SOME_ENGINE_H
SomeEngine.cpp
#include "SomeEngine.h"
template<>
EngineA& SomeEngine::getEngine( Param a, Param b, Param c ) {
return getEngineA( a, b, c );
}
template<>
EngineB& SomeEngine::getEngine( Param a, Param b, Param c ) {
return getEngineB( a, b, c );
}
上面的功能模板設計模式使我能夠使用一個通用的getEngine()
調用來使類專門化以返回適當的Engine Type,從而可以正常工作。 我有一個非類成員函數模板, class Engine
將class Engine
作為其模板參數之一...這在任何類之外的同一標題中以及它將使用的前兩個類之后定義。
template<class Engine, typename T>
T generateVal( Param a, Param b, Param c ) {
static T retVal = 0;
static Engine engine = SomeEngine::getEngine<Engine>( a, b , c );
}
以上工作除此處顯示的功能不完整外。 它依賴於另一個類。 另一類本身的模式與上述類似。 它具有一個已刪除的默認構造函數,以及一堆用於返回不同類型對象的靜態方法。 但是,在第二類中,幾乎所有靜態方法本身都是函數模板,其中一些具有重載版本,而另一些具有多個模板參數。 它也在上面的相同頭文件中聲明。 看起來像這樣:
class SomeOther {
public:
SomeOther() = delete;
template<class IntType = int>
static otherA<IntType>& getOtherA( IntType a, IntType b );
template<class RealType = double>
static otherB<RealType>& getOtherB( RealType a, RealType B );
template<class IntType = int>
static otherC<IntType>& getOtherC( IntType a );
template<class RealType = double>
static otherD<RealType>& getOtherD( RealType a );
template<class IntType = int>
static otherE<IntType>& getOtherE();
template<class IntType = int>
static otherE<IntType>& getOtherE( IntType a, IntType b );
template<class IntType = int>
static otherE<IntType>& getOtherE( std::initializer_list<double> a );
template<class IntType = int, class X>
static otherE<IntType>& getOtherE( std::size_t a, double b, double c, X x );
};
我正在嘗試與上面的第二個類做類似的事情,以具有通用的函數模板,這樣我就可以將模板參數class Other
傳遞給它,但class Other
依賴於其自己的模板參數,並且內部函數調用可能有所不同參數數量。
這使我開始使用可變參數模板來聲明此類的功能。
我嘗試過這樣的事情:
template< typename Type,
template<typename, class...> class Other,
class... OtherParams,
class... FuncParams>
static Other<Type, OtherParams...>& getOther( FuncParams... params );
然后,我上面顯示的功能還沒有完成,在添加對第二類的支持時,我嘗試了以下操作:
template< class Engine,
typename Type,
template<typename, class...> class Other,
class... OtherParams,
class... FuncParams>
Type generate( Param a, Param b, Param c, FuncParams... params ) {
static Type retVal = 0;
static Engine engine = SomeEngine::getEngine<Engine>( a, b, c );
static Other<Type, OtherParams...> other = SomeOther::getOther<Type, Other<Type, OtherParams...>> ( params... );
retVal = other( engine );
return retVal;
}
這就是我將使用上面的第二類的方式。 這是我嘗試在對應的cpp文件中專門化幾個getOther()函數的嘗試
template<typename Type,
template<typename, class...> class Other,
class... OtherParams,
class... FuncParams>
otherA<Type>& SomeOther::getOther( FP... params ) {
return getOtherA( params... );
}
template<typename Type,
template<typename, class...> class Other,
class... OtherParams,
class... FuncParams>
otherB<Type>& SomeOther::getOther( FP... params ) {
return getOtherB( params... );
}
這不會編譯,它抱怨函數定義與現有聲明不匹配。 我什至試圖在頭文件中寫一個重載,並且不斷出現相同的錯誤。 我不知道這是否是語法錯誤。 我已經嘗試了很多要在此處列出的內容,我在各處搜索了類似內容,但似乎找不到任何相關內容。
我想知道是否可以做這樣的事情; 如果是,則需要在上面進行什么更改,以便至少進行編譯和構建; 因此我可以在運行時開始對其進行測試; 然后繼續添加其他現有類型。
我想嘗試保持與第一類相同的設計模式。 我的獨立函數模板是將要調用的函數,具體取決於其模板參數; 它應該知道要調用哪個引擎-其他類型。
在第二種情況下,實際上您不是在嘗試部分專門化getOther
。 部分專業化應該這樣寫:
class Tmp
{
public:
template<class A, class B>
void bar(A a, B b) {}
};
template<class A>
void Tmp::bar<A, int>(A a, int b) {}
並且GCC將給出錯誤消息:
error: non-class, non-variable partial specialization 'bar<A, int>' is not allowed
void Tmp::bar<A, int>(A a, int b) {}
因此,在第二種情況下,您實際上是在實現之前聲明的方法,並且編譯器無法找到匹配的聲明。
為了解決此問題,由於C ++不允許部分專業化,因此可以使用函數重載。 這是一個示例(它在GCC上編譯,但在VS2017上編譯失敗,更像是MSVC的問題,但我不確定):
template <class T>
class otherA
{
T t;
public:
otherA(T t) : t(t) {}
void WhoAmI() { cout << "I'm OtherA" << endl; }
T getValue() { return t; }
};
template <class T, class X>
class otherE
{
T t;
public:
otherE(T t) : t(t) {}
void WhoAmI() { cout << "I'm OtherE" << endl; }
T getValue() { return t; }
};
class SomeOther {
public:
SomeOther() = delete;
template<class IntType = int>
static otherA<IntType>& getOtherA(IntType a, IntType b)
{
static otherA<IntType> A(a);
return A;
}
template<class IntType = int, class X>
static otherE<IntType, X>& getOtherE(IntType a, double b, double c, X x)
{
static otherE<IntType, X> E(a);
return E;
}
template<template<typename, class...> class Other,
class Type,
class... OtherParams,
class... FuncParams>
static Other<Type, OtherParams...>& getOther(FuncParams... params)
{
return getOther<Type, OtherParams...>(params...);
}
private:
/// Function Overloading
template<class T,
class... FuncParams>
static otherA<T>& getOther(FuncParams... params)
{
return getOtherA<T>(params...);
}
template<class T,
class X,
class... FuncParams>
static otherE<T, X>& getOther(FuncParams... params)
{
return getOtherE<T, X>(params...);
}
};
template<
class Type,
template<typename, class...> class Other,
class... OtherParams,
class... FuncParams>
Type test(FuncParams... params) {
static Other<Type, OtherParams...>& other = SomeOther::getOther<Other, Type, OtherParams...>(params...);
other.WhoAmI();
return other.getValue();
}
class foo{};
int main()
{
int AValue = test<int, otherA>(1, 2);
cout << "AValue: " << AValue << endl;
int EValue = test<int, otherE, foo>(3, 2.1, 2.2, foo());
cout << "EValue: " << EValue << endl;
return 0;
}
和輸出將是
I'm OtherA
AValue: 1
I'm OtherE
EValue: 3
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.