I want to do a simple thing:
void DoUntil(auto predicate = [] { return false; });
Obviously this doesn't work - I have to use a template argument:
template <typename P>
void DoUntil(P predicate = [] { return false; });
But this statement doesn't work either - the Clang gives an error:
error: no matching function for call to …
note: candidate template ignored: couldn't infer template argument 'P'
If I do call the function without arguments, somehow compiler fails to deduce type from a default argument:
int main() { DoUntil(); }
I don't want to use std::function<>
in any way.
Are there any other possible solutions to my problem?
A lambda is an anonymous type with no default constructor (of cause, you can use its copy/move constructor if available). If you must go the lambda way, you can do:
namespace detail{ auto predicate = [] { return false; }; }
template <typename P = decltype(detail::predicate)>
void DoUntil(P pred = detail::predicate);
Rather than trying to fiddle around with lambdas. You can go the good old way:
namespace detail{
struct DefaultPredicate{ bool operator()() const { return false; } };
}
template <typename P = detail::DefaultPredicate>
void DoUntil(P predicate = P{});
Or better still as Kyle Strand answered.
Use function overloading instead of the default argument feature. Create a non-template function that takes no arguments in addition to the template function:
void DoUntil() ;
template <typename P>
void DoUntil(P predicate) ;
The no-argument version can simply invoke the template version with the lambda you want to use as the default predicate:
void DoUntil() { DoUntil([] { return false; }); }
The problem with your original approach is that you're trying to provide a default template specialization by specifying a default argument value, but without specifying a default template-type. Even without involving lambdas, the following won't work because T
doesn't have a default type, even though t
has a default value:
template <typename T>
void Foo(T t = 3);
What's needed is to specify a default type for T
using <typename T = int>
.
As noted in WhiZTiM's answer, the default type for the case involving the lambda function must be deduced using decltype
. This is of course because lambdas have unique types known only to the compiler.
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