我刚刚提交了this bug on 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都支持它。
我见过this SO question但是没有请求或给出变通方法,这正是我正在寻找的。 p>
虽然不是超级关键(显然我多年来一直没有变量模板)但这种模式对于我想做的一些工作和我想做的一些文章特别重要。用于序列化,脚本绑定等的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 bug有没有解决方法?或者使用可变参数模板在VC ++ 12中使用(编译时)函数指针参数的任何其他方法?
答案 0 :(得分: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上。