我有一個模板C++模板偏特:成員函數
template <int a, int b>
class MyTemplateClass
{
// ....
void computeSomething();
};
,我想部分專門用於B的兩種特殊情況:
不過,據我所知,部分專業化對於成員功能無效。我怎樣才能達到我想要的?還有其他解決方案嗎?謝謝!
我有一個模板C++模板偏特:成員函數
template <int a, int b>
class MyTemplateClass
{
// ....
void computeSomething();
};
,我想部分專門用於B的兩種特殊情況:
不過,據我所知,部分專業化對於成員功能無效。我怎樣才能達到我想要的?還有其他解決方案嗎?謝謝!
一個可能的方法是estract compute()
,只爲它創建一個基類並專門化這個基類。
我的意思是......如果你創建fooSub
template <int a, int b>
struct fooSub
{
void compute()
{ std::cout << "- foo generic compute()" << std::endl; }
};
template <int a>
struct fooSub<a, 2>
{
void compute()
{ std::cout << "- foo compute() for 2" << std::endl; }
};
template <int a>
struct fooSub<a, 3>
{
void compute()
{ std::cout << "- foo compute() for 3" << std::endl; }
};
一個通用版本和兩個專業可以在「專注」通過繼承在foo
簡單地計算如下
template <int a, int b>
struct foo : public fooSub<a, b>
{ };
另一種可能的解決方案,如果您至少可以使用C++ 11,則使用SFINAE(std::enable_if
)啓用/禁用不同版本的compute()
,如下面的bar
類
template <int a, int b>
struct bar
{
template <int bb = b>
typename std::enable_if<(b == bb) && (b != 2) && (b != 3)>::type
compute()
{ std::cout << "- bar generic compute()" << std::endl; }
template <int bb = b>
typename std::enable_if<(b == bb) && (b == 2)>::type compute()
{ std::cout << "- bar compute() for 2" << std::endl; }
template <int bb = b>
typename std::enable_if<(b == bb) && (b == 3)>::type compute()
{ std::cout << "- bar compute() for 3" << std::endl; }
};
遵循兩種方式
#include <iostream>
#include <type_traits>
template <int a, int b>
struct fooSub
{
void compute()
{ std::cout << "- foo generic compute()" << std::endl; }
};
template <int a>
struct fooSub<a, 2>
{
void compute()
{ std::cout << "- foo compute() for 2" << std::endl; }
};
template <int a>
struct fooSub<a, 3>
{
void compute()
{ std::cout << "- foo compute() for 3" << std::endl; }
};
template <int a, int b>
struct foo : public fooSub<a, b>
{ };
template <int a, int b>
struct bar
{
template <int bb = b>
typename std::enable_if<(b == bb) && (b != 2) && (b != 3)>::type
compute()
{ std::cout << "- bar generic compute()" << std::endl; }
template <int bb = b>
typename std::enable_if<(b == bb) && (b == 2)>::type compute()
{ std::cout << "- bar compute() for 2" << std::endl; }
template <int bb = b>
typename std::enable_if<(b == bb) && (b == 3)>::type compute()
{ std::cout << "- bar compute() for 3" << std::endl; }
};
int main()
{
foo<0, 1>{}.compute(); // print - foo generic compute()
foo<1, 2>{}.compute(); // print - foo compute() for 2
foo<2, 3>{}.compute(); // print - foo compute() for 3
bar<2, 1>{}.compute(); // print - bar generic compute()
bar<3, 2>{}.compute(); // print - bar compute() for 2
bar<4, 3>{}.compute(); // print - bar compute() for 3
}
非常乾淨的解決方案,謝謝! – macmallow
由於模板的類型名稱是已知的,你可以添加一些實施computeSomething
功能,分支流程,就像這樣:
template <int a, int b>
class MyTemplateClass
{
// ....
void computeSomething()
{
if (b == 2) { computeWith2(); }
else if (b == 3) { computeWith3(); }
else { computerNormally(); }
};
}
一種方法是從這個類的計算提取到一個單獨的一個。
然後你就可以專注只計算類:
template <int a, int b>
class MyTemplateClass
{
// ....
void computeSomething() {
Computation<a, b> c;
c.compute();
}
};
template <int a, int b>
struct Computation { void compute() {} };
template <int a>
struct Computation<a, 2> { void compute() {} };
template <int a>
struct Computation<a, 3> { void compute() {} };
雖然國際海事組織,最好不使用專業化,而是不同(描述!)的名稱和編譯時間條件兩者之間進行選擇:
template<bool Condition,
typename Then,
typename Else>
using if_t = typename std:: conditional<
Condition, Then, Else>:: type;
template <int a, int b>
class MyTemplateClass
{
// ....
using Computation =
if_t<b == 2,
B2Comp<a>,
if_t<b == 3,
B3Comp<a>,
DefaultComp<a, b> > >;
void computeSomething() {
Computation c;
c.compute();
}
};
// Add (template) classes, B3Comp and DefaultComp
如果你已經可以嘗試C++ 17,則上述可改寫爲:
template <int a, int b>
class MyTemplateClass
{
// ....
void computeSomething() {
if constexpr (b == 2) {
B2Comp<a> comp;
comp.compute();
} else if constexpr (b == 3) {
B3Comp<a> comp;
comp.compute();
} else {
DefaultComp<a, b> comp;
comp.compute();
// Or just put the code here, if it's short
}
}
};
您可以使用模板函數來代替模板類。
如果避免評估「不需要」的代碼路徑,從而可以在那裏放置其他不合格的代碼(如同一個模板的遞歸實例化),與使用正常代碼相反。
您需要部分專業類或者做處理特定的主類專業化幾個重載模板方法一個完整的編譯例子。 – VTT