繁体   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