Разрешен ли нерасширенный пакет параметров в аргументе шаблона сигнатуры функции для шаблона класса? (Возможная ошибка VS2013)

0

Является ли пакет нерасширенных параметров допустимым в сигнатуре функции, являющейся параметром шаблона для другого шаблона?

Я ожидаю, что это так, но я получаю разные результаты от разных компиляторов. Следующий минимальный пример работает с 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;
};
  • 0
    @Yakk Якк, это будет опечатка. У меня работает код с исправлением в VS2013. Вы исправили это, я думаю?
  • 0
    @Jarod42 Jarod42, действительно. Исправлена. Когда я писал этот последний комментарий, передо мной не было компилятора, и мой компилятор мозга не так хорош.
Теги:
c++11
templates
visual-c++

1 ответ

0
Лучший ответ

Выглядит очень похоже на ошибку VS, так как это абсолютно правильное расширение шаблона для использования. По моему опыту реализация VS вариаций чрезвычайно шелушащаяся.

Тем не менее, этот основной шаблон:

template <typename ...Args>
struct MakeTupleOfTypes;

должен действительно не быть varadic, так как шаблон принимает только один TypeList:

template <typename ArgsList>
struct MakeTupleOfTypes;
  • 0
    Вы бы сказали, что иметь неправильный шаблон вариации для первоначального определения? Я согласен, что в этом случае нет необходимости, но будут ли это иметь плохие последствия (кроме добавления ненужной сложности)?
  • 0
    Да. Если пользователь случайно передаст слишком много аргументов, он получит «создание экземпляра неопределенного шаблона» вместо «слишком много аргументов». Так что это делает сообщения об ошибках хуже.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню