简体   繁体   English

是否允许在类模板的函数签名模板参数中使用未扩展的参数包? (可能的VS2013错误)

[英]Is an unexpanded parameter pack in a function signature template argument for a class template allowed? (Possible VS2013 bug)

Is an unexpanded parameter pack allowed in a function signature that is a template parameter to another template? 在作为另一个模板的模板参数的函数签名中是否允许使用未扩展的参数包?

I expect that it is, but I get different result from different compilers. 我希望是这样,但是我从不同的编译器得到不同的结果。 The following minimal example works with Apple LLVM version 6.0 and gcc 4.8.1 but not VS2013. 以下最小示例适用于Apple LLVM 6.0版和gcc 4.8.1,但不适用于VS2013。

Example in Ideone: http://ideone.com/xuyhRb Ideone中的示例: http ://ideone.com/xuyhRb

From my searching, this may be a bug in VS2013, possibly related to: Parameter pack expansion fails However, the solutions given there do not work, the problem seems to be specific to having the unexpanded parameter pack in the function signature. 从我的搜索来看,这可能是VS2013中的错误,可能与以下内容有关: 参数包扩展失败但是,此处给出的解决方案不起作用,问题似乎特定于函数签名中具有未扩展的参数包。 If we replace this in VS2013 with another template to create the function type, it compiles. 如果我们在VS2013中将其替换为另一个模板以创建函数类型,则会对其进行编译。

#include <functional>
#include <string>
#include <tuple>
#include <iostream>

using namespace std;

template<typename ...Args>
struct TypeList {};

typedef TypeList<int, float, string> Types;

template <typename ...Args>
struct MakeTupleOfTypes;

template <typename ...Args>
struct MakeTupleOfTypes<TypeList<Args...>>
{
    typedef tuple<Args...> type;
};

template <typename ...Args>
struct MakeTupleOfFunction;

template <typename ...Args>
struct MakeTupleOfFunction<TypeList<Args...>>
{
    typedef tuple<function<void(Args)>...> type; // <-- VS2013 error here
};


typedef TypeList<int, float, string> Types;
typedef MakeTupleOfTypes<Types>::type TupleOfTypes;
typedef MakeTupleOfFunction<Types>::type TupleOfFunctions;

void f1(int x) { cout << x << endl; }
void f2(float x) { cout << x << endl; }
void f3(string x) { cout << x << endl; }

int main()
{
    TupleOfTypes values;
    get<0>(values) = 42;
    get<1>(values) = 3.14159;
    get<2>(values) = "Hello, World!";

    TupleOfFunctions functions;
    get<0>(functions) = &f1;
    get<1>(functions) = &f2;
    get<2>(functions) = &f3;

    get<0>(functions)(get<0>(values));
    get<1>(functions)(get<1>(values));
    get<2>(functions)(get<2>(values));

    return 0;
}

Visual Studio fails with: Visual Studio失败,出现:

error C3520: 'Args': parameter pack must be expanded in this context.

at the line 在行

Fix for VS2013: use this template to avoid having an unexpanded parameter pack in the function signature. VS2013的修复:使用此模板可以避免函数签名中包含未扩展的参数包。

template <typename Arg>
struct MakeFunction
{
    typedef function<void(Arg)> type;
};

and

template <typename ...Args>
struct MakeTupleOfFunction<TypeList<Args...>>
{
    typedef tuple<typename MakeFunction<Args>::type...> type;
};

Looks very much like a VS bug to me, since that's a perfectly valid pattern expansion to use. 在我看来,这非常像VS错误,因为这是可以使用的完全有效的模式扩展。 VS's variadics implementation is extremely flaky, in my experience. 根据我的经验,VS的变量实现非常不稳定。

That said, this primary template: 也就是说,这个主要模板:

template <typename ...Args>
struct MakeTupleOfTypes;

should really not be varadic, since the template only accepts one TypeList : 因为模板只接受一个TypeList ,所以它实际上不应是TypeList

template <typename ArgsList>
struct MakeTupleOfTypes;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM