I have been using a variadic template that acts as an exception firewall in an interface between C and C++. The template simply takes a function, followed by N arguments and calls the function inside a try catch block. This has been working fine, unfortunately one of the functions I wish to call now takes an additional default argument. As a result the function name is not resolved and the template fails to compile.
The error is:
perfect-forward.cpp: In function
‘void FuncCaller(Func, Args&& ...) [with Func = void (*)(const std::basic_string<char>&, double, const std::vector<int>&), Args = {const char (&)[7], double}]’
:
perfect-forward.cpp:69:41: instantiated from here
perfect-forward.cpp:46:4: error: too few arguments to function
A simplified version of the code is as follows:
template< class Func, typename ...Args >
void FuncCaller( Func f, Args&&... params )
{
try
{
cout << __func__ << " called\n";
f(params...);
}
catch( std::exception& ex )
{
cout << "Caught exception: " << ex.what() << "\n";
}
}
void Callee( const string& arg1, double d, const vector<int>&v = vector<int>{} )
{
cout << __func__ << " called\n";
cout << "\targ1: " << arg1 << "\n";
cout << "\td: " << d << "\n";
cout << "\tv: ";
copy( v.begin(), v.end(), ostream_iterator<int>( cout, " " ) );
cout << "\n";
}
int main()
{
vector<int> v { 1, 2, 3, 4, 5 };
FuncCaller( Callee, "string", 3.1415, v );
FuncCaller( Callee, "string", 3.1415 ); **// Fails to compile**
return 0;
}
Should this code work or am I expecting too much from the compiler?
Note: I have tested the use of perfect forwarding with constructors that have default arguments and the code compiles and works as expected,
i.e.:
template<typename TypeToConstruct> struct SharedPtrAllocator
{
template<typename ...Args> shared_ptr<TypeToConstruct>
construct_with_shared_ptr(Args&&... params) {
return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...));
};
};
works when calling the cfollowing constructor with 2 or 3 arguments...
MyClass1( const string& arg1, double d, const vector<int>&v = vector<int>{} )
I don't think there's any way this can be achieved. The default argument values are not part of the function signature. They're only code-generation short-hands that are expanded by the compiler when you call the function literally. Similarly, std::bind
won't pick up default arguments, either.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With