[英]curiously recurring template pattern and infinite recursion
看看下面這個簡單的重復出現的模板模式 (CRTP) 示例:
template<class Derived>
struct base
{
void foo() {
static_cast<Derived*>(this)->foo();
}
};
struct derived
: public base<derived>
{};
由於除了從base
派生的成員函數外, derived
沒有其他成員函數foo
,因此調用derived{}.foo()
產生無限遞歸。 我們可以修改base::foo
的定義,使得static_cast<Derived*>(this)->foo()
僅在有Derived::foo
時才被調用嗎?
編輯:我問的原因是我實際應用程序中的foo
有一個模板參數。 由於模板方法不能是虛擬的,CRTP 似乎是唯一的解決方法。
我們可以修改
base::foo
的定義,使得static_cast<Derived*>(this)->foo()
僅在有Derived::foo
時才被調用嗎?
在Derived::foo
強制定義的一種方法是使用虛擬參數重載函數。
template <typename Derived>
struct base
{
void foo() {
static_cast<Derived*>(this)->foo(0); // Requires Derived::foo(int)
}
};
或者
template <typename Derived>
struct base
{
void foo(int ) {
static_cast<Derived*>(this)->foo(); // Requires Derived::foo(void)
}
};
如果您願意將base::foo
的返回類型更改為虛擬標簽,我們可以檢查調用Derived::foo
返回相同的標簽,並取決於調用派生版本。
#include <iostream>
template<class Derived>
class base
{
private:
struct Tag {};
public:
Tag foo() {
if constexpr (!std::is_same_v<decltype(std::declval<Derived>().foo()), Tag>) {
static_cast<Derived*>(this)->foo();
}
return {};
}
};
struct derived
: public base<derived>
{};
struct derived2
: public base<derived>
{
void foo() { std::cout << "foo!"; }
};
int main() {
derived d;
derived2 d2;
d.foo();
d2.foo();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.