Могут ли аргументы функции по умолчанию "заполнять" для расширенных пакетов параметров?

Следующий код не удается скомпилировать:

#include <iostream>

template<typename F, typename ...Args>
static auto wrap(F func, Args&&... args)
{
    return func(std::forward<Args>(args)...);
}

void f1(int, char, double)
{
    std::cout << "do nada1\n"; 
}

void f2(int, char='a', double=0.)
{
    std::cout << "do nada2\n"; 
}

int main()
{
    wrap(f1, 1, 'a', 2.); 
    wrap(f2, 1, 'a'); 
}
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

main.cpp: In instantiation of 'auto wrap(F, Args&& ...) [with F = void(*)(int, char, double); Args = {int, char}]':
main.cpp:22:20:   required from here
main.cpp:6:44: error: too few arguments to function
     return func(std::forward<Args>(args)...);

Похоже, что соблюдается правило "пакеты параметров, являющиеся последними" (по крайней мере, в объявлении), и после расширения должен быть сформирован правильный вызов функции: f2 может быть вызван с 1, 2 или 3 аргументами поэтому ошибка too few arguments кажется "суровой". Это также не выглядит как проблема дедукции (которая была бы моей догадкой, но из-за сообщения об ошибке)

Является ли это отсутствующей функцией или существует нарушение со стандартной точки зрения?

Ответ 1

Вы не вызываете функцию с аргументами по умолчанию из шаблона.

Вы вызываете функцию-указатель, который указывает на функцию, ожидающую ровно 3 аргумента, ни больше, ни меньше.

Конечно, компилятор с горечью жалуется на недостающую третью.

Вы можете делать то, что вы пытаетесь сделать там с помощью вариационного функтора, поскольку С++ 14 даже lambda:

wrap([](auto&&... args){return f2(std::forward<decltype(args)>(args)...);}, 1, 'a');