我正在尝试创建一个实用程序类,它将在列表中的所有类上调用特定函数。这背后的目的是在类的层次结构中自动化反射元素。
我使用Visual Studio 2015编译一些C ++代码,并且当递归模板函数展开时我收到编译错误,因为编译器在区分递归函数和终止函数时遇到问题。
我已经将课程的核心提取到一个简单的测试用例中:
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 &)'
在Visual Studio 2015中编译时,会导致以下错误:
{{1}}
我之前从未使用过变量模板,所以我有点不知道为什么会出错。任何帮助将不胜感激!
答案 0 :(得分:2)
您的问题可以按照以下方式最小化:
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);
}