Как вызвать функцию с аргументами по умолчанию из шаблонной функции без указания значений для аргументов по умолчанию?
Я попробовал следующий код:
#include <iostream>
#include <functional>
int anyFunc(int a, int b, int c = 0, int d = 0) {
return a + b + c + d;
}
template <class T, class F>
T callFunc2(const std::function<F> & func, T a, T b) {
return func(a, b);
}
int main() {
std::cout << callFunc2<int, decltype(anyFunc)>(anyFunc, 5, 5) << std::endl;
}
Но он выдает ошибку. GCC 9.3.0:
prog.cc: In instantiation of 'T callFunc2(const std::function<_Signature>&, T, T) [with T = int; F = int(int, int, int, int)]':
prog.cc:14:65: required from here
prog.cc:10:16: error: no match for call to '(const std::function<int(int, int, int, int)>) (int&, int&)'
10 | return func(a, b);
| ~~~~^~~~~~
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/functional:59,
from prog.cc:2:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/std_function.h:683:5: note: candidate: '_Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int, int, int, int}]'
683 | function<_Res(_ArgTypes...)>::
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/std_function.h:683:5: note: candidate expects 4 arguments, 2 provided
Т. е. нужно указать 4 аргумента вместо 2. Но почему? Ведь 2 аргумента по умолчанию.
Ответы (2 шт):
Откуда компилятору знать о том, что именно вызывается в шаблоне? По-вашему, это может быть и функция от двух, и от четырех аргументов... Аргументы по умолчанию - это не более чем подсказка для конкретного явного вызова функции.
"По-моему, так" (с) Пух
Как всегда, спасает косвенность :)
#include <iostream>
int anyFunc(int a, int b, int c = 0, int d = 0) {
return a + b + c + d;
}
template <class T, class F>
T callFunc4(F func, T a, T b, T c = T(), T d = T()) {
return func(a, b, c, d);
}
template <class T, class F>
T callFunc2(F func, T a, T b) {
return func(a, b);
}
int main() {
std::cout << callFunc4(anyFunc, 5, 5) << std::endl;
std::cout << callFunc2([](int a, int b){ return anyFunc(a,b); }, 5, 5) << std::endl;
}
Этот пример показывает, что аргументов по-умолчанию следует избегать и использовать вместо них перегруженные функции.
int anyFunc(int a, int b, int c) {
return anyFunc(a, b, c, 0);
}
int anyFunc(int a, int b) {
return anyFunc(a, b, 0);
}
В этом случае также будет возможность при необходимости поставить точку останова при вызове функции с аргументами по-умолчанию. Также эти аргументы не будут создаваться в вызывающем коде (для int это не важно, но с при работе с более большими объектами - очень даже).