Passing different lambdas to function template in c++ -


i have class foo accepts different predicate variants through constructor.

template<typename t> struct value {     t value; };  class foo { public:     template<typename t>     foo(value<t> &value, function<bool()> predicate)     {     }      template<typename t>     foo(value<t> &value, function<bool(const value<t> &)> predicate) :         foo(value, function<bool()>([&value, predicate](){ return predicate(value); }))     {     } }; 

this allows me construct class explicit function object:

value<int> i; foo foo0(i, function<bool()>([]() { return true; })); foo foo1(i, function<bool(const value<int> &)>([](const auto &) { return true; })); 

however fails when trying use lambda directly:

foo fool1(i, [](const value<int> &) { return true; }); 

for reason don't understand yet compiler not consider availability of implicit conversion lambda function in constructor template. error message (visual c++ 2015, update 3):

error c2664: 'foo::foo(foo &&)': cannot convert argument 2 'main::< lambda_f1d2143f356d549800fb3412d8bc61a2>' 'std::function< bool (void)>'

now can add constructor template lambdas

template<typename t, typename unarypredicate> foo(value<t> &value, unarypredicate predicate) :     foo(value, function<bool(const value<t> &)>(predicate)) { } 

which work fine long lambda passed constructor has 1 parameter of value<t>, naturally fails lambdas without parameter:

foo fool0(i, []() { return true; }); 

so need sfinae magic enable appropriate constructor template different lambdas, like:

template<typename t, typename unarypredicate,     typename = enable_if_t<is_callable_without_args> > foo(value<t> &value, unarypredicate predicate) :     foo(value, function<bool()>(predicate)) { }  template<typename t, typename unarypredicate,     typename = enable_if_t<is_callable_with_one_arg> > foo(value<t> &value, unarypredicate predicate) :     foo(value, function<bool(const value<t> &)>(predicate)) { } 

or maybe 1 constructor template trick, like:

template<typename t, typename unarypredicate> foo(value<t> &value, unarypredicate predicate) :     foo(value, function<???decltype(unarypredicate)???>(predicate)) { } 

or maybe different solution? question how enable constructor overloads work appropriate lambdas.

your problem c++ treats arguments equally, , attempts deduce template arguements of them.

failure deduce template arguments used error, not inconsistent deduction. doesn't take ones match , "go it".

we can mark template argument non-deduced:

template<class t> struct tag_t {using type=t;}; template<class tag> using type=typename tag::type;  template<class t> using block_deduction = type<tag_t<t>>; 

then:

template<class t> foo(   value<t> &value,   block_deduction<function<bool(const value<t> &)>> predicate ) :   foo(     value,     [&value, predicate=std::move(predicate)]{ return predicate(value); }   ) {} 

now t deduced first argument. normal conversion occurs 2nd.

(minor formatting changes/optimizations/code shortening applies foo beyond block_deduction included.)


Comments

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -