为啥我不能将模板函数指针传递给可变参数函数?

Posted

技术标签:

【中文标题】为啥我不能将模板函数指针传递给可变参数函数?【英文标题】:Why can't I pass template function pointers to varargs functions?为什么我不能将模板函数指针传递给可变参数函数? 【发布时间】:2013-11-21 00:06:30 【问题描述】:

以下 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 (*)()!

【问题讨论】:

VS2013 有可变参数模板。你有什么理由不使用这些吗? @chris VS2013 完全支持可变参数模板?在 vs12 中它不存在。可能跑题了,但我只是想知道? 刚刚推出的新 CTP 参见:blogs.msdn.com/b/vcblog/archive/2013/11/18/…,也是 C++ 功能路线图 @me.deeiip,是的,它是内置的。2012 有一个 CTP 与他们一起,它被提升为内置支持。 顺便说一句,这段代码在 Linux 中使用 GCC 4.7.2 在 C++11 模式下编译,当然,一旦我将“wmain”替换为“main”。 【参考方案1】:

问题是 Visual Studio 在尝试将模板函数传递给“...”之前没有正确或完全实例化它。

这是一个解决方案,它为您提供(几乎)相同的客户端代码语法,并且可以在 Visual Studio 2010 上编译和工作。诀窍是将模板噱头隐藏在更标准的接口继承中。代码有点复杂,但仍然可以管理和安全。不过,不确定这是否适用于您的“现实生活”问题,您可能会简化为在这里发布您的问题。

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;

【讨论】:

以上是关于为啥我不能将模板函数指针传递给可变参数函数?的主要内容,如果未能解决你的问题,请参考以下文章

将可变参数模板参数包传递给下一个函数

可变参数模板调度程序

如何将构造函数(可变参数)作为模板参数传递?

将可变参数函数模板参数传递给另一个函数

如何将矢量(或类似)传递给可变参数模板

给定传递给它的参数类型,如何确定函数参数的类型?