Является ли пакет нерасширенных параметров допустимым в сигнатуре функции, являющейся параметром шаблона для другого шаблона?
Я ожидаю, что это так, но я получаю разные результаты от разных компиляторов. Следующий минимальный пример работает с Apple LLVM версии 6.0 и gcc 4.8.1, но не VS2013.
Пример в Ideone: http://ideone.com/xuyhRb
Из моего поиска это может быть ошибка в VS2013, возможно, связанная с: Ошибка расширения пакета параметров. Однако решения, предоставленные там, не работают, проблема, похоже, связана с наличием пакета нерасширенных параметров в сигнатуре функции. Если мы заменим это в 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:
error C3520: 'Args': parameter pack must be expanded in this context.
на линии
Исправить для VS2013: используйте этот шаблон, чтобы избежать наличия пакета необязательных параметров в сигнатуре функции.
template <typename Arg>
struct MakeFunction
{
typedef function<void(Arg)> type;
};
а также
template <typename ...Args>
struct MakeTupleOfFunction<TypeList<Args...>>
{
typedef tuple<typename MakeFunction<Args>::type...> type;
};
Выглядит очень похоже на ошибку VS, так как это абсолютно правильное расширение шаблона для использования. По моему опыту реализация VS вариаций чрезвычайно шелушащаяся.
Тем не менее, этот основной шаблон:
template <typename ...Args>
struct MakeTupleOfTypes;
должен действительно не быть varadic, так как шаблон принимает только один TypeList
:
template <typename ArgsList>
struct MakeTupleOfTypes;