- Default arguments with std::function - 6 Updates
- brace initialization of subclasse of array - 1 Update
JiiPee <no@notvalid.com>: Sep 16 11:23AM +0100 void foo(int a=6) {} std::function<void(int)> f; f(); // does not work How can I create a fuction object which understands default arguments? like I would like to call here f(); but this does not compile. Thanks you |
"Öö Tiib" <ootiib@hot.ee>: Sep 16 04:28AM -0700 On Saturday, 16 September 2017 13:24:03 UTC+3, JiiPee wrote: > f(); // does not work > How can I create a fuction object which understands default arguments? > like I would like to call here f(); but this does not compile. Thanks you Perhaps I do not understand your problem but callability of object is implemented as operator() so all what you need is to have default argument of operator() of your function object: int main() { struct F { void operator()(int a = 6) {} } f; f(); f(42); } |
JiiPee <no@notvalid.com>: Sep 16 12:33PM +0100 On 16/09/2017 12:28, Öö Tiib wrote: > f(); > f(42); > } Thanks, something to try. But I think I really need to use this std::function here, because the real problem i have is to use it with templates, so I need to use std::function in my code. Your example does not use std::function. In my real code i have something like: function f = foo<1>; and foo is a template function with default parameters. So i want to use f: f(1); f(); |
SG <s.gesemann@gmail.com>: Sep 16 06:07AM -0700 Am Samstag, 16. September 2017 13:33:26 UTC+2 schrieb JiiPee: > Thanks, something to try. But I think I really need to use this > std::function here, because the real problem i have is to use it with > templates, so I need to use std::function in my code. That does not sound like an explanation for why you need std::function. > So i want to use f: > f(1); > f(); OK. But--as you know--it doesn't work. If f is of type std::function<void(int)> it will have the following function call operator: void operator()(int) const; and there is no default argument there, regardless of how you initialize this function object. Now, you could write your own functor like this: struct myfunction { std::function<void(int)> inner; void operator()(int i=6) const { return inner(i); } }; But this 6 here is a static property of myfunction. As such, you can't change it at runtime and it doesn't depend on how yo initialize inner. If you want to support changing default arguments you could do: struct myfunction { std::function<void(int)> inner; int current_default; void operator()(int i) const { return inner(i); } void operator()() const { return inner(current_default); } }; But C++ doesn't let you access default arguments. So, if you have void foo(int = 6); there is no way of extracting the default argument of foo. The only way of making use of this default argument is by calling the function directly by name without arguments. That's it. So, you would have to replicate the default argument where you initialize myfunction: myfunction mf = { &foo, 6 }; mf(); mf(42); I don't see a way around it -- unless perhaps you *always* expect there to be a default argument, in which case you *could* do this: void foo(int = 6); struct myfunction { std::function<void()> inner1; std::function<void(int)> inner2; void operator()() const { return inner1(); } void operator()(int i) const { return inner2(i); } }; int main() { myfunction mf = { []{foo();}, foo }; mf(); mf(42); } Here, foo is directly used within the lambda expression and without an explicit argument. This makes the compiler lookup what foo is. It finds the above declaration with the default argument and basically turns the call foo() into foo(6) under the hood. But ... you don't really wanna do that! Try to avoid it if possible. Cheers! sg |
JiiPee <no@notvalid.com>: Sep 16 02:42PM +0100 On 16/09/2017 14:07, SG wrote: > myfunction mf = { &foo, 6 }; > mf(); > mf(42); interesting idea. thanks. Seems like operator() is the way to go. I ll play around with these |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Sep 16 06:02PM +0200 On 9/16/2017 12:23 PM, JiiPee wrote: > f(); // does not work > How can I create a fuction object which understands default arguments? > like I would like to call here f(); but this does not compile. Thanks you There is as far as I know no way to obtain the argument default values programmatically. As soon as you pass a stand-alone function around, even as a template parameter, information about the argument defaults is lost. However, when the original function is a member function of a class, a functor, that /type/ can be passed around, and the function can then be called with defaults: #include <iostream> #include <memory> // std::(unique_ptr, make_unique) #include <utility> // std::move using namespace std; struct Foo { void action( int const a = 6 ) const { cout << "Foo " << a << endl; } }; struct Bar { void action( int const a = 6 ) const { cout << "Bar " << a << endl; } }; template< class Some_type > struct Type_carrier_ {}; struct Abstract_callable { virtual void action() const = 0; virtual void action( int ) const = 0; virtual auto clone() const -> unique_ptr<Abstract_callable> = 0; }; template< class Type > struct Specific_callable : Abstract_callable { void action() const override { Type{}.action(); } void action( int const a ) const override { Type{}.action( a ); } auto clone() const -> unique_ptr<Abstract_callable> override { return unique_ptr<Abstract_callable>{ new Specific_callable{ *this } }; } }; class Callable { private: unique_ptr<Abstract_callable> impl_; public: void operator()() const { impl_->action(); } void operator()( int const a ) const { impl_->action( a ); } template< class Action_provider > Callable( Type_carrier_<Action_provider> ) : impl_{ make_unique< Specific_callable< Action_provider > >() } {} Callable( Callable const& other ) : impl_{ other.impl_->clone() } {} Callable( Callable&& other ) : impl_{ move( other.impl_ ) } {} }; void do_stuff( Callable const& f ) { f(); f( 42 ); } auto main() -> int { do_stuff( Callable{ Type_carrier_<Foo>{} } ); do_stuff( Callable{ Type_carrier_<Bar>{} } ); } The key point of this code being that `Callable` is a concrete, non-templated type whose instances carry the requisite knowledge. Instead of separate `operator()` implementations in `Callable`, you can just define a single templated one that forwards its arguments. Cheers & hth., - Alf |
"Öö Tiib" <ootiib@hot.ee>: Sep 16 02:03AM -0700 On Thursday, 14 September 2017 13:22:05 UTC+3, Ralf Goertz wrote: > So why doesn't a > subclass of vector inherit its list-initialization constructors? Because language rules (IMHO fortunately) do not suggest anywhere that subclass should somehow automatically inherit all constructors. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment