determine first arg of callable
I need some help to extract the type of a callable which is passed as argument to the ctor of X. struct X { template< typename Fn > X( Fn fn) { ... code which evaluates Fn and extracts the type of the first arg of Fn } }; void f( int) {...} struct A { void operator()( char) {...} void g( string) {... } }; The code should evaluate in the ctor to the arguments of the callables: A a; X x1( f); -> int X x2( a); -> char X x3( bind( & A::g, a, _1) ); -> string I could overload the ctor of X for function pointers: template< typename Arg > X( void(*fn)( Y< Arg > &) ) {...} but how to deal with the other two callable types? result_of and function_traits did not work for me. Oliver
On 15 May 2013 09:35, Oliver Kowalke wrote:
I could overload the ctor of X for function pointers:
template< typename Arg > X( void(*fn)( Y< Arg > &) ) {...}
but how to deal with the other two callable types? result_of and function_traits did not work for me.
In general there is no unique argument_type for callable objects, they could have overloaded function call operators. If http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3579.html makes it into the standard you could find out the argument type *for a given invocation* i.e. you can ask "what is the type of the first argument when called as f(x, y, z)", but not "what is the argument_type of F"
On 15/05/13 10:35, Oliver Kowalke wrote:
I need some help to extract the type of a callable which is passed as argument to the ctor of X.
struct X { template< typename Fn > X( Fn fn) { ... code which evaluates Fn and extracts the type of the first arg of Fn } };
You can't do that. Just change your code to not require it.
2013/5/15 Mathias Gaunard
On 15/05/13 10:35, Oliver Kowalke wrote:
I need some help to extract the type of a callable which is passed as argument to the ctor of X.
struct X { template< typename Fn > X( Fn fn) { ... code which evaluates Fn and extracts the type of the first arg of Fn } };
You can't do that. Just change your code to not require it.
that is not possible at least what I can do is to overload the ctor: template< typename Arg > X( void(*fn)( Arg &) ) {...} template< typename Arg > X( boost::function< void( Arg &) > fn) {...} ctor is called then: X x1( g); // OK A a; boost::function< void( Y< char > &) > f1=boost::bind( & A::operator(), a, _1); X x2( f1); boost::function< void( Y< int > &) > f2=boost::bind( g, _1); X x3( f2); For function pointer it's OK - but the code using function<> and bind() looks a little bit clumsy: X x2(boost::bind( & A::operator(), a, _1)); // will not compile
On 15/05/13 15:13, Oliver Kowalke wrote:
2013/5/15 Mathias Gaunard
On 15/05/13 10:35, Oliver Kowalke wrote:
I need some help to extract the type of a callable which is passed as argument to the ctor of X.
struct X { template< typename Fn > X( Fn fn) { ... code which evaluates Fn and extracts the type of the first arg of Fn } };
You can't do that. Just change your code to not require it.
that is not possible
Then I suggest you change the design.
013/5/15 Mathias Gaunard
that is not possible
Then I suggest you change the design.
the class has to accept a callable object (function pointer or functor) - what is known is that it does return void and takes one argument. this is not a design decision, it is required by the user. as I showed in my example it can be solved - maybe a solution would be to overload the ctor with the type returned by boost::bind(). but what about C++11 lambdas.
On Wed, May 15, 2013 at 5:38 PM, Oliver Kowalke
the class has to accept a callable object (function pointer or functor) - what is known is that it does return void and takes one argument. this is not a design decision, it is required by the user. as I showed in my example it can be solved - maybe a solution would be to overload the ctor with the type returned by boost::bind().
The bind function objects do not have a single operator(), and their operators() are templates.
but what about C++11 lambdas.
Lambdas with no captured variables are convertible to function pointers.
13/5/15 Andrey Semashev
On Wed, May 15, 2013 at 5:38 PM, Oliver Kowalke
wrote:
the class has to accept a callable object (function pointer or functor) - what is known is that it does return void and takes one argument. this is not a design decision, it is required by the user. as I showed in my example it can be solved - maybe a solution would be to overload the ctor with the type returned by boost::bind().
The bind function objects do not have a single operator(), and their operators() are templates.
OK - some simple code: struct B { virtual void run() = 0; }; template< typename Fn > struct D : public B { Fn fn; D( Fn fn_) : fn( fn_) {} void run() { fn(...) } // argument construction omitted }; struct X { B * b; template< typename Fn > X( Fn fn) : b( 0) { b = new D< Fn >( fn); } void run() { b->run(); } }; Constraints to Fn: returns void and has only one argument. I need to know in X::X() or D::run() what's the first and only argument of Fn. I believe the problem should be solvable - for function pointers it is easy, X() could be overloaded with function<>. The only remaining issue are objects created by bind() and passed to the ctor - I thought overloading X() with the type returned by bind() should work?!
On Wed, May 15, 2013 at 6:07 PM, Oliver Kowalke
OK - some simple code:
struct B { virtual void run() = 0; };
template< typename Fn > struct D : public B { Fn fn;
D( Fn fn_) : fn( fn_) {}
void run() { fn(...) } // argument construction omitted };
struct X { B * b;
template< typename Fn > X( Fn fn) : b( 0) { b = new D< Fn >( fn); }
void run() { b->run(); } };
Constraints to Fn: returns void and has only one argument. I need to know in X::X() or D::run() what's the first and only argument of Fn.
It doesn't follow from the code above. If D is the same for all Fns then I don't see how D can discover the type (and value) of the argument to pass. The way your design looks it seems the other way around - it is D who defines the argument type and value, and Fn should be able to accept it.
I believe the problem should be solvable - for function pointers it is easy, X() could be overloaded with function<>. The only remaining issue are objects created by bind() and passed to the ctor - I thought overloading X() with the type returned by bind() should work?!
No, bind function object types do not have the argument types. These types are not known until the function object is actually invoked. The only types you will find is the bound function object type and bound argument values types (and the latter may differ from the actual argument types, BTW).
No, bind function object types do not have the argument types. These types are not known until the function object is actually invoked. The only types you will find is the bound function object type and bound argument values types (and the latter may differ from the actual argument types, BTW).
This is an aside, but is there a way, given the result of a bind(), to get the types of the bound argument values? Thanks, Nate
On Thu, May 16, 2013 at 10:25 AM, Nathan Ridge
No, bind function object types do not have the argument types. These types are not known until the function object is actually invoked. The only types you will find is the bound function object type and bound argument values types (and the latter may differ from the actual argument types, BTW).
This is an aside, but is there a way, given the result of a bind(), to get the types of the bound argument values?
For boost::bind you can use visit_each [1] or decompose the bind_t template type manually. Both ways are not quite documented, but it is doable. For other bind implementations the code may differ but the same types should be present in some form in the function object type. [1] http://www.boost.org/doc/libs/release/libs/bind/bind_visitor.cpp
No, bind function object types do not have the argument types. These types are not known until the function object is actually invoked. The only types you will find is the bound function object type and bound argument values types (and the latter may differ from the actual argument types, BTW).
This is an aside, but is there a way, given the result of a bind(), to get the types of the bound argument values?
For boost::bind you can use visit_each [1] or decompose the bind_t template type manually. Both ways are not quite documented, but it is doable. For other bind implementations the code may differ but the same types should be present in some form in the function object type.
[1] http://www.boost.org/doc/libs/release/libs/bind/bind_visitor.cpp
Interesting, thanks! Do you know of a (standard) way to do it for std::bind? Thanks, Nate
On Thu, May 16, 2013 at 11:22 AM, Nathan Ridge
No, bind function object types do not have the argument types. These types are not known until the function object is actually invoked. The only types you will find is the bound function object type and bound argument values types (and the latter may differ from the actual argument types, BTW).
This is an aside, but is there a way, given the result of a bind(), to get the types of the bound argument values?
For boost::bind you can use visit_each [1] or decompose the bind_t template type manually. Both ways are not quite documented, but it is doable. For other bind implementations the code may differ but the same types should be present in some form in the function object type.
[1] http://www.boost.org/doc/libs/release/libs/bind/bind_visitor.cpp
Interesting, thanks!
Do you know of a (standard) way to do it for std::bind?
No, I think this will be implementation-dependent.
On 15 May 2013 15:07, Oliver Kowalke wrote:
The only remaining issue are objects created by bind() and passed to the ctor - I thought overloading X() with the type returned by bind() should work?!
As I already said in the first reply in this thread, in the general case there is no such thing as "the argument type" of a callable object, and in the specific case of boost::bind the call wrapper it returns is a template that just forwards its arguments to the target object. How do you tell the argument type of a function template? If your design requires something that is unknowable then the design is flawed. Requiring callable objects to have a single, fixed argument_type is an outdated C++98 notion incompatible with forwarding call wrappers like the one returned by boost::bind.
013/5/15 Peter Dimov
You've omitted the only interesting part.
template< typename Arg > struct Q {...}; struct B { virtual void run() = 0; }; template< typename Fn, typename Arg > struct D : public B { Fn fn; D( Fn fn_) : fn( fn_) {} void run() { Q< Arg > q; fn( q) } // argument construction omitted }; struct X { B * b; template< typename Fn > X( Fn fn) : b( 0) { typedef typename Magic< Fn >::arg1_type arg_type; b = new D< Fn, arg_type >( fn); } void run() { b->run(); } }; I want to construct a Q<> in D::run() and pass it to fn. Magic<> can be specialized for raw function pointers, function<> etc.
This still doesn't quite explain it. Let's say that my fn takes a
std::string. How does D know what string to pass? An empty string? "foo"?
"hello world"? Where does the argument value come from?
-----Original Message-----
From: Oliver Kowalke
Sent: Wednesday, May 15, 2013 18:52
To: boost
Subject: Re: [boost] determine first arg of callable
013/5/15 Peter Dimov
You've omitted the only interesting part.
template< typename Arg > struct Q {...}; struct B { virtual void run() = 0; }; template< typename Fn, typename Arg > struct D : public B { Fn fn; D( Fn fn_) : fn( fn_) {} void run() { Q< Arg > q; fn( q) } // argument construction omitted }; struct X { B * b; template< typename Fn > X( Fn fn) : b( 0) { typedef typename Magic< Fn >::arg1_type arg_type; b = new D< Fn, arg_type >( fn); } void run() { b->run(); } }; I want to construct a Q<> in D::run() and pass it to fn. Magic<> can be specialized for raw function pointers, function<> etc. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
2013/5/15 Peter Dimov
This still doesn't quite explain it. Let's say that my fn takes a std::string. How does D know what string to pass? An empty string? "foo"? "hello world"? Where does the argument value come from?
Fn does takes a Q< std::string > not a plain std::string (I've omitted this detail in my first example). Q<> might be default constructable.
template< typename Arg > struct Q {...};
does something irrelevant
struct B { virtual void run() = 0; };
interface
template< typename Fn, typename Arg > struct D : public B { Fn fn;
D( Fn fn_) : fn( fn_) {}
void run() { Q< Arg > q; fn( q) } // argument construction omitted };
concrete implementation - calls default ctor of Q< Arg > in D::run() and passes instance of Q< Arg > to fn
struct X { B * b;
template< typename Fn > X( Fn fn) : b( 0) { typedef typename Magic< Fn >::arg1_type arg_type; b = new D< Fn, arg_type >( fn); }
void run() { b->run(); } };
bundles the stuff void g( Q< std::string > &) {...} X x( g); x.run(); // call g() with an instance of Q< std::string > as arg struct W { void h( Q< int > &) {...} }; W w; X x( bind( & W::h, w, _1) ); x.run(); // call W::h() with an instance of Q< int > as arg
2013/5/16 Oliver Kowalke
2013/5/15 Peter Dimov
This still doesn't quite explain it. Let's say that my fn takes a std::string. How does D know what string to pass? An empty string? "foo"? "hello world"? Where does the argument value come from?
Fn does takes a Q< std::string > not a plain std::string (I've omitted this detail in my first example). Q<> might be default constructable.
template< typename Arg > struct Q {...};
does something irrelevant
struct B { virtual void run() = 0; };
interface
template< typename Fn, typename Arg > struct D : public B { Fn fn;
D( Fn fn_) : fn( fn_) {}
void run() { Q< Arg > q; fn( q) } // argument construction omitted };
concrete implementation - calls default ctor of Q< Arg > in D::run() and passes instance of Q< Arg > to fn
struct X { B * b;
template< typename Fn > X( Fn fn) : b( 0) { typedef typename Magic< Fn >::arg1_type arg_type; b = new D< Fn, arg_type >( fn); }
void run() { b->run(); } };
bundles the stuff
void g( Q< std::string > &) {...} X x( g); x.run(); // call g() with an instance of Q< std::string > as arg
struct W { void h( Q< int > &) {...} }; W w; X x( bind( & W::h, w, _1) ); x.run(); // call W::h() with an instance of Q< int > as arg
I can hardly imagine the real use case.
Will the following acceptable?
X x(feed(fn)); // call fn() with an instance of Q<int> as arg
where feed<Arg>(F) returns a wrapper that explicitly describes the arg.
2013/5/15 Mathias Gaunard
On 15/05/13 18:30, Oliver Kowalke wrote:
void run() {
Q< Arg > q; fn( q) } // argument construction omitted };
concrete implementation - calls default ctor of Q< Arg > in D::run() and passes instance of Q< Arg > to fn
How can you pass a Q<Arg> to a function expecting an Arg?
because Fn takes a Q< Arg > as argument? as I wrote - in the prvious example I omitted the detail of Q<>.
On 15/05/13 19:34, Oliver Kowalke wrote:
2013/5/15 Mathias Gaunard
On 15/05/13 18:30, Oliver Kowalke wrote:
void run() {
Q< Arg > q; fn( q) } // argument construction omitted };
concrete implementation - calls default ctor of Q< Arg > in D::run() and passes instance of Q< Arg > to fn
How can you pass a Q<Arg> to a function expecting an Arg?
because Fn takes a Q< Arg > as argument? as I wrote - in the prvious example I omitted the detail of Q<>.
Yet in your code it takes an Arg, not a Q<Arg>.
Oliver Kowalke wrote:
void g( Q< std::string > &) {...} X x( g); x.run(); // call g() with an instance of Q< std::string > as arg
struct W { void h( Q< int > &) {...} }; W w; X x( bind( & W::h, w, _1) ); x.run(); // call W::h() with an instance of Q< int > as arg
Interesting. Can't you get away with just passing the type to X, or even the Q<> value itself? X x( fn, Q<int>() ); Otherwise, your problem doesn't have a solution in general, consider struct Fn { template<class T> void operator()( Q<T> & qt ); };
2013/5/15 Peter Dimov
Oliver Kowalke wrote:
void g( Q< std::string > &) {...}
X x( g); x.run(); // call g() with an instance of Q< std::string > as arg
struct W { void h( Q< int > &) {...} }; W w; X x( bind( & W::h, w, _1) ); x.run(); // call W::h() with an instance of Q< int > as arg
Interesting. Can't you get away with just passing the type to X, or even the Q<> value itself?
X x( fn, Q<int>() );
I tried to hide the information of Q< int > for the user - in the considered context it would confuse the user. Anyway - I've another idea, maybe it will solve my problem. Thx!
On 15/05/13 15:38, Oliver Kowalke wrote:
013/5/15 Mathias Gaunard
that is not possible
Then I suggest you change the design.
the class has to accept a callable object (function pointer or functor)
The Callable concept does not require that the function be monomorphic nor does it provide a way to know what the type of the argument is. So what you want is inconsistent with the Callable concept.
On Wed, May 15, 2013 at 5:13 PM, Oliver Kowalke
at least what I can do is to overload the ctor:
template< typename Arg > X( void(*fn)( Arg &) ) {...}
template< typename Arg > X( boost::function< void( Arg &) > fn) {...}
ctor is called then:
X x1( g); // OK
A a; boost::function< void( Y< char > &) > f1=boost::bind( & A::operator(), a, _1); X x2( f1);
boost::function< void( Y< int > &) > f2=boost::bind( g, _1); X x3( f2);
For function pointer it's OK - but the code using function<> and bind() looks a little bit clumsy:
X x2(boost::bind( & A::operator(), a, _1)); // will not compile
The last one is equivalent to just X x2(a); You could try something like this: class X { public: template< typename R, typename A0 > X(R (*p)(A0)) {} template< typename R, typename A0, typename A1 > X(R (*p)(A0, A1)) {} ... template< typename R, typename C, typename A0 > X(R (C::*p)(A0)) {} template< typename R, typename C, typename A0, typename A1 > X(R (C::*p)(A0, A1)) {} ... template< typename T > X(T f) : X(&T::operator()) {} }; This will not work with templated or overloaded operator() (and for this reason will not work with bind). But I agree that you should avoid this design.
participants (7)
-
Andrey Semashev
-
Jonathan Wakely
-
Mathias Gaunard
-
Nathan Ridge
-
Oliver Kowalke
-
Peter Dimov
-
TONGARI