Параметры после функции параметров в функции

Я смог найти один вопрос на SO, который, кажется, задает тот же или похожий вопрос, что и я, но ответов нет: - (

Я хочу добавить параметр без шаблона после пакета параметров. Я не слишком хорошо знаком со стандартной спецификацией С++ для вариативных шаблонов/пакетов параметров, но мое предположение о здравом смысле говорит мне, что самые правые параметры, переданные функции, будут сначала заполнены в параметры размещения, затем остальные будут заполнены в пакет параметров. Однако я не могу заставить свой тестовый код работать как с g++, так и с clang++. Пример кода ниже.

#include <vector>
#include <iostream>

int Subscribe(int channel, int callback)
{
    return channel;
}

// This one works fine...
template<typename... T>
std::vector<int> SubscribeMultiple1(int callback, T&&... channels)
{
    return {
        Subscribe(std::forward<T>(channels), std::move(callback))...
    };
}

// This one does not work; all I did was move `int callback` after the parameter pack.
template<typename... T>
std::vector<int> SubscribeMultiple2(T&&... channels, int callback)
{
    return {
        Subscribe(std::forward<T>(channels), std::move(callback))...
    };
}

int main()
{
    auto subs = SubscribeMultiple2(1, 2, 3);

    for (auto sub : subs)
    {
        std::cout << "Sub: " << sub << '\n';
    }
}

Live Sample

Итак, мой первый вопрос: почему параметр non-template не работает после пакета параметров? Я что-то делаю неправильно или это запрещено языком?

Во-вторых, есть ли способ получить синтаксис, который я пытаюсь сделать? Я упростил свой образец, но в моем реальном коде параметр callback действительно равен std::function<...>. Идея состоит в том, что я могу подписаться на несколько "идентификаторов событий", а обратный вызов определяется в конце. Наличие обратного вызова в конце лучше для читаемости и стиля. Пример:

SubscribeMultiple(EventOne, EventTwo, EventThree, [] {
    // Implement callback code here when any of the above
    // three events are fired.
});

Если мне нужно иметь обратный вызов спереди, это менее читаемо ИМХО. Поэтому я готов попробовать любое обходное решение для получения синтаксиса и структуры, к которой я стремился. Спасибо заранее.

Ответ 1

Я делаю что-то неправильно или это запрещено языком?

Вывод пакетов параметров происходит только тогда, когда пакет является последним аргументом.

[temp.deduct.type]/5.7:

Невыводимые контексты:

  • [...]
  • Пакет параметров функции, который не встречается в конце списка объявлений-параметров.

Так что нормальное поведение стандартного С++.

Есть ли способ получить синтаксис, который я пытаюсь сделать?

Использовать первый синтаксис в качестве обходного пути:

   template<typename... T>
   std::vector<int> SubscribeMultiple1(int callback, T&&... channels)