8

我刚刚在 Microsoft Connect 上提交了这个关于无法编译以下玩具代码片段的错误:

template <typename... P> struct S {
    template <void(*F)(P...)> static void T() { }
};

void A(int, float) { }
int main() { S<int, float>::T<&A>(); }

错误是:

test.cpp(2): error C3520: 'P' : parameter pack must be expanded in this context

本质上,当用作模板参数时,我无法在函数签名中解压缩可变参数类型。这段代码(我认为)是合法的;至少,GCC 4.7、Clang 3.0 和 ICC 13 都支持它。

我已经看到了这个 SO question,但没有请求或给出解决方法,这就是我正在寻找的。

虽然不是超级关键(显然我多年来一直没有可变参数模板),但这种模式对于我想做的一些工作和我想做的关于 C++ 的一些文章特别重要11 种用于序列化、脚本绑定等的反射技术,这是我希望对 Visual Studio 用户有用的东西(因为它是迄今为止我所在行业中占主导地位的编译器工具集)。我希望微软的工程师能够在 2013 RTM 之前解决这个问题,但我并没有屏住呼吸。

一个玩具(这次来自记忆)如何使用它的示例是这样的(减去使它更容易使用的宏):

Reflect<MyType>("MyType")
.bind("GetMatrix", mat44, &MyType::GetMatrix>()
.bind("Display", void, &MyType::Display>();

当然,这一切都可以在没有可变参数模板的情况下完成。当然,它只需要大量代码并接受对绑定成员函数的最大数量的限制。是的,将函数作为模板参数传递是很重要的,因为成员函数指针在 Visual Studio 中的工作方式(可变大小)以及实现与Impossibly Fast C++ Delegates相当的效率的愿望(在我的利基市场中) C++ 社区,这种优化水平有时实际上很重要)这否定了使用std::function或类似设计的选项。

是否有解决此 VS 错误的方法?或者任何其他使用可变参数模板在 VC++12 中使用(编译时)函数指针参数的方法?

4

1 回答 1

6

不知道为什么,但使用 typedef 进行简化似乎可行:

template <typename... P>
struct S
{
    typedef void (*MyFunc)(P...);

    template <MyFunc myFunc>
    static void foo() {}
};

void foo2(int, float) {}

int main()
{
    S<int, float>::foo<&foo2>();
}

至少在 Visual Studio 2013 Ultimate Preview 上。

于 2013-07-01T08:48:57.180 回答