以下C ++代码在Visual Studio 2013中无法为我编译:
#include <stdarg.h>
#include <stdio.h>
#include <wchar.h>
template <int X>
int Function()
{
return X;
}
int Sum(int start, ...)
{
va_list args;
va_start(args, start);
for (;;)
{
typedef int (*Callback)(); // typedef required by C standard 7.15.1.1
Callback func = va_arg(args, Callback);
if (!func)
break;
start += (*func)();
}
va_end(args);
return start;
}
int wmain()
{
wprintf(L"sum: %d\n", Sum(5, Function<32>, Function<66>, static_cast<int (*)()>(nullptr)));
return 0;
}
但是,我收到以下错误:
mycode.cpp(32):错误C2664:'int Sum(int,...)':无法转换参数 2从'int(__ cdecl *)(void)'到'...' 上下文不允许消除重载函数的歧义
我知道这个错误通常意味着什么;它表示你的函数已经重载,所以你不能使用函数指针,除非你将它转换为解决重载的类型。但在这种情况下,没有歧义:类型总是int(*)()!
答案 0 :(得分:0)
问题是Visual Studio在尝试将模板函数传递给“...”之前没有正确或完全实例化。
这是一个解决方案,它为您提供(几乎)相同的客户端代码语法,并在Visual Studio 2010上编译和工作。诀窍是将模板gimmick隐藏在更标准的接口继承中。代码有点复杂,但仍然可管理和安全。不确定这是否适用于您的“现实生活”问题,您可能会简化为在此发布您的问题。
class IFunctor {
public:
virtual ~IFunctor() {}
virtual int value() = 0;
};
template<int X> class Functor : public IFunctor {
public:
virtual ~Functor() {}
virtual int value() { return X; }
};
template<int X> IFunctor* Function()
{
static Functor<X> x;
return &x;
}
IFunctor *EndFunction()
{
return nullptr;
}
int Sum(int start, ...)
{
va_list args;
va_start(args, start);
for (;;)
{
IFunctor *functor = va_arg(args, IFunctor*);
if (functor == nullptr) break;
start += functor->value();
}
va_end(args);
return start;
}
int main()
{
wprintf(L"sum: %d\n", Sum(5, Function<32>(), Function<66>(), EndFunction()));
char c = getc(stdin);
return 0;
}