為什么C 禁止這種部分專業化?
這種禁止的背后是什么樣的哲學,讓我可以接受它?
如果沒有這個禁令,編程會容易得多。
模板應防止冗余。
模板應防止出現冗余。
現在我必須為每一個帶有int d = 3的N類產生冗余。
//__________________________________________
//__________________________________________
// //
template<class N, int d>
class MyClass
{
public:
void doo()。
};
//__________________________________________
//__允許的_______________________________。
//
template<class N, int d>
void MyClass<N, d>::doo()
{
cout << "general"。
}
//__________________________________________
//__禁止的_____________________________。
//
template<class N>
void MyClass<N, 3>::doo( )
{
cout << "部分專業化"。
}
uj5u.com熱心網友回復:
首先,你需要對類本身進行部分專業化。就是這個類是一個模板。它的成員函式是一個非模板函式。 一個類的部分專業化可以在其定義上有所不同。也就是說,它們可以有不同的成員集。
例如
template<class N, int d>
class MyClass
{
public:
void doo()。
};
template<class N, int d>
void MyClass<N, d>::doo()
{
std::cout << "General";
}
template<class N>
class MyClass<N, 3>
{
public:
void doo()。
};
template<class N>
void MyClass<N, 3>::doo( )
{
std::cout << "部分專業化"。
}
至于函式模板,它們有自己的函式多載和函式特殊化機制。
uj5u.com熱心網友回復:
你可以先對類進行部分專業化,然后為專業化后的類實作方法:
template<class N, int d>
class MyClass
{
public:
void doo()。
};
template<class N>
class MyClass<N, 3>
{
public:
void doo()。
};
template<class N, int d>
void MyClass<N, d>::doo()
{
std::cout << "General
"。
}
template<class N>
void MyClass<N, 3>::doo( )
{
std::cout << "partial specialization
"。
}
int main()
{
MyClass<int, 1> o1{}; o1.doo()。
MyClass<int, 3> o3{}; o3.doo() 。
}
// Outputs //一般
//部分特殊化 //部分特殊化
uj5u.com熱心網友回復:
函式的部分專業化是一件非常非常棘手的事情,尤其是當你允許多載函式的時候。
它可能會導致不可專門化的函式,或者專門化發生在意外的多載上,或者專門化永遠不能被呼叫。
我最好的建議是遠離函式的專業化。
而對于你的問題,我想說,最好是簡單地使用C 17 if constexpr:
template<class N, int d>。
void MyClass<N, d>::doo()
{
if constexpr (d !=3) {
cout << "General";
} else{
cout << "只有當d == 3"。
}
uj5u.com熱心網友回復:
我過去經常依賴模式匹配,這使我經常容易受到語言的這種限制,對此我從未找到一個優雅的實用解決方案。 我想我本能地學會了遠離這種設計,盡管我仍然偶爾會遇到這種情況。
我知道的解決方案有四種:
我知道的解決方案有四種:
我知道的解決方案有四種。
- 現代解決方案(
if constexpr),(實用但不優雅,IMO)。 - 經典的解決方案(在現實世界中不實用)。
- 經典解決方案 CRTP (實用但優雅?)
- "深奧 "的解決方案,
enable_if(不優雅的 IMO) 。
這篇文章主要闡述了第3個問題。
這些解決方案中沒有一個能讓我100%滿意。 我看不出有什么基本的理由,當語言遇到一個專門的成員函式宣告時,不能直接對模板類進行專業化處理,至少要有限制。
現代的解決方案(在一個答案中顯示)是在一般版本中使用
if constexpr。
我發現這就像作弊一樣,而且它不優雅,我同意你的觀點,一定有辦法在模板內做到這一點。
當然,經典的解決方案也是其他答案中所顯示的。 然而,我認為這并不實用,原因是
MyClass<N, 3>通常在其宣告和實作上與一般情況下的MyClass<N, d>非常相似,因此我們必須為每種情況(部分)專門重復MyClass的整個實作。
這對我來說是不可接受的。
例如,考慮一下如果你有一個更復雜的類會發生什么:
template<class N, int d>
class MyClass
{
public:
void A() const{....}。
void B() const{....}。
.
.
.
void Z() const{....}。
void doo(){std::cout << "general";}; }
};
不一定,但有可能你還需要有大量重復的代碼:
template<class N>
class MyClass<N, 3>
{
void A() const{....}.
void B() const{....}。
.
.
.
void Z() const{....}。
void doo()。
};
我想不出一個最糟糕的DRY(Don't repeat yourself)違規案例。
我發現的解決方案是提取
MyClass中絕對常見的部分:
template<class MyClassCRTP>
class BasicMyClass<MyClassCRTP> // eventually we need will need to know the derived class.
{
public:
void A() const{....}。
void B() const{....}。
.
.
.
void Z() const{....}。
};
template<class N, int d>
class MyClass : BasicMyClass<MyClass<N, d> >
{
public:
void doo(){std::cout << "general";};?
};
template<class N>
class MyClass<N, 3> : BasicMyClass<MyClass<N, 3> >
{
void doo()。
};
現在你可以對MyClass<N, 3>::doo進行專業化處理,而不需要太多的重復代碼。
這真的很優雅嗎?我不知道。 它確實也打開了其他的麻煩事。 當然不是很理想,我們想對一個(方法)函式進行專業化處理,結果是我們有了額外的類!
這是不理想的。
最后,為了完整起見,有一個神秘的解決方案,并不比
if constexpr好,但在某種程度上向后兼容 IMO:
template<class N, int d>。
class MyClass
{
public:
template<class Dummy, std::enable_if<d ! = 3 and sizeof(Dummy*), int> = 0>
void doo(){std::cout << "general";}。
template<class Dummy, std:: enable_if<d == 3 and sizeof(Dummy*), int> = 0>
void doo(){std::cout << "special";}; };cout << "special";< ; }
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/329615.html
標籤:
