gpt4 book ai didi

c++ - 可变参数模板中递归模板函数的终止问题

转载 作者:行者123 更新时间:2023-11-30 03:30:28 25 4
gpt4 key购买 nike

我正在尝试创建一个实用程序类,它将调用列表中所有类的特定函数。这背后的目的是在类的层次结构中自动化反射元素。

我正在使用 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);
}

live example on godbolt

关于c++ - 可变参数模板中递归模板函数的终止问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44927329/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com