簡體   English   中英

奇怪的重復模板模式和無限遞歸

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM