Saturday, September 16, 2017

Digest for comp.lang.c++@googlegroups.com - 7 updates in 2 topics

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: