簡體   English   中英

可變模板中遞歸模板函數的終止問題

[英]Termination issue on recursive template function in variadic template

我正在嘗試創建一個實用程序類,該實用程序類將在列表中的所有類上調用特定函數。 其背后的目的是使類的層次結構中的反射元素自動化。

我正在使用Visual Studio 2015編譯一些C ++代碼,並且在遞歸模板函數展開時遇到編譯錯誤,因為編譯器在區分遞歸函數和終止函數時遇到麻煩。

我已經將類的核心提取到一個簡單的測試用例中:

#include <iostream>

template< typename ... BaseClasses >
class Meta
{
public:
    virtual ~Meta() {}

    template< typename T >
    void call(const T& val)
    {
        callOnAllClasses<T, BaseClasses...>(val);
    }

private:
    template< typename T, typename HeadClass >
    void callOnAllClasses(const T& val)
    {
        auto pObj = dynamic_cast<HeadClass*>(this);
        if ( pObj )
            pObj->HeadClass::doSomething(val);
    }

    template< typename T, typename HeadClass, typename ... TailClasses >
    void callOnAllClasses(const T& val)
    {
        auto pObj = dynamic_cast<HeadClass*>(this);
        if ( pObj )
            pObj->HeadClass::doSomething(val);
        callOnAllClasses<T, TailClasses...>(val);
    }
};

class A
{
public:
    void doSomething(int i)
    {
        std::cout << "A:" << i << std::endl;
    }
};

class B
{
public:
    void doSomething(int i)
    {
        std::cout << "B:" << i << std::endl;
    }
};

class C : public B, public A, public Meta<C,B,A>
{
    public:
    void doSomething(int i)
    {
        std::cout << "C:" << i << std::endl;
    }
};

int main()
{
    C c;
    c.call(5);
}

在Visual Studio 2015中編譯時會導致以下錯誤:

error C2668: 'Meta<C,B,A>::callOnAllClasses': ambiguous call to overloaded function
could be 'void Meta<C,B,A>::callOnAllClasses<T,A,>(const T &)'
or       'void Meta<C,B,A>::callOnAllClasses<T,A>(const T &)'

我以前從未使用過可變參數模板,所以對於為什么會出錯,我有點茫然。 任何幫助將非常感激!

您的問題可以最小化,如下所示:

template< typename ... Bases >
struct Meta
{
    template< typename T >
    void call(const T& val)
    {
        callOnAllClasses<T, Bases...>(val);
    }

    template< typename T, typename HeadClass >
    void callOnAllClasses(const T& val)
    {

    }

    template< typename T, typename HeadClass, typename ... TailClasses >
    void callOnAllClasses(const T& val)
    {
        callOnAllClasses<T, TailClasses...>(val);
    }
};

struct C : Meta<int, int, int> { };

int main()
{
    C{}.call(5);
}

TailClasses為空時,這兩個簽名對於編譯器都是模棱兩可的:

template< typename T, typename HeadClass >
void callOnAllClasses(const T& val);

template< typename T, typename HeadClass, typename ... TailClasses >
void callOnAllClasses(const T& val);

TailClasses為空時,在遞歸的情況下添加一個額外的模板參數有助於編譯器消除可變重載和非可變重載之間的歧義。

template< typename T, typename HeadClass, typename T1, typename ... TailClasses >
void callOnAllClasses(const T& val)
{
    auto pObj = dynamic_cast<HeadClass*>(this);
    if ( pObj )
        pObj->HeadClass::doSomething(val);
    callOnAllClasses<T, T1, TailClasses...>(val);
}

實時演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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