I have the following code:
#include <functional>
//...
typedef int (*Myfun)(int);
std::function<int (int)> fn0([](int a)->int {
return -a;
});
std::cout << "val == " << fn0(3) << std::endl; //"val == -3"
Myfun *fptr = fn0.target<Myfun>(); //fptr is NULL!!
std::cout << "val == " << (*fptr)(3) << std::endl; //Access violation error
Actually, this code is a code from MSDN with a slight change: using lambda instead of a plain function.
Why does the call fn0.target<Myfun>() returns NULL?
When I declare a regular function
int neg(int val) {
return (-val);
}
and write std::function<int (int)> fn0(neg);, everything seems to work, but lambda is not been handled correctly.
The type Myfun from typedef int (*Myfun)(int); is not related to the type of the function's target, which is the unique, unnamed type of the closure object produced by executing the expression [](int a)->int { return -a; }
Try executing std::cout << fn0.target_type().name() << '\n'; to see for yourself.
When you declare a function with int neg(int val) { return (-val); }, the type of neg is exactly Myfun (after function-to-pointer conversion, which happens in std::function<int(int)> fn0(neg)), which is why std::function::target() is able to return a pointer to it.
Cubbi explained why your code doesn't work -- a lambda is not a function pointer.
Now, trivial lambdas can be converted to function pointers. So supposed you really want to force that conversion?
template<typename F>
struct as_pointer_t {
F f;
template<typename R, typename... Args>
operator type<R(*)(Args...)>() const { return {f}; }
template<typename R, typename... Args>
operator std::function<R(Args...)>() const { return (R(*)(Args...))f; }
};
template<typename F>
as_pointer_t<F> as_pointer( F&& f ) { return {std::forward<F>(f)}; }
now we can do this:
int main() {
typedef int (*Myfun)(int);
std::function<int (int)> fn0(as_pointer([](int a)->int {
return -a;
}));
std::cout << "val == " << fn0(3) << std::endl; //"val == -3"
Myfun *fptr = fn0.target<Myfun>(); //fptr is no longer NULL!!
std::cout << "val == " << (*fptr)(3) << std::endl;
}
and your code works as expected. However, the above only compiles if your lambda captures nothing.
If your goal is to convert a capturing lambda to a function pointer, you cannot. You can store the state in a global variable, and use it in a non-capturing lambda. You can also convert a capturing lambda into a function-pointer and void* pair.
I have written code that takes a compile-time index to inject the void* into the list (and an optional type to use instead of void*), and produces said pair of void* and function pointer. The general case is tricky -- the specific case (say, the first argument) is far easier.
template<typename T> using type=T;
template<typename F, typename X=void*>
struct callback_t {
F f;
operator X() { return X(&f); }
template<typename R, typename...Args>
operator type<R(*)(X, Args...)>() const {
return []( X x, Args... args )->R {
F* f = (F*)(x);
return (*f)(std::forward<Args>(args)...);
};
}
};
template<typename X=void*, typename F>
callback_t<F,X> make_callback( F f ) {
return {std::forward<F>(f)};
}
use:
typedef void(*pfun)(void*, int);
void call_pfun( pfun f, void* p) {
for (int i = 0; i < 3; ++i)
f( p, i );
}
int main()
{
int y = 7;
auto callback = make_callback([y]( int x ) { std::cout << x+y << "\n"; });
call_pfun( callback, callback );
}
live example.
Related
I need to do something like this:
template<class A=B, class B>
A fn(B x) { return A(x); };
int main()
{
int i = fn(5); // Error, no matching overload found
double d = fn<double>(5);
};
Hence, a function template which deduces the types automatically from the function arguments, but the caller can change the first one if needed. Any way to do this?
You can simply use constexpr if in such cases like:
struct NO_TYPE;
template<class RET_TYPE = NO_TYPE, class IN_TYPE>
auto fn(IN_TYPE x)
{
if constexpr ( std::is_same_v< RET_TYPE, NO_TYPE> )
{
std::cout << "1" << std::endl;
return IN_TYPE(x);
}
else
{
std::cout << "2" << std::endl;
return RET_TYPE(x);
}
}
int main()
{
int i = fn(5); // Error, no matching overload found
double d = fn<double>(5);
};
So I have a function where, using C++17, I'm able to apply any method from any object:
#include <functional>
template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
std::invoke(method, object, args...);
}
What I ask: Is there a way to improve this to require less work for the caller of the function when the method is overloaded.
Example use with overloaded methods:
#include <iostream>
class Foo
{
int bottles;
public:
void Edit ()
{
bottles = 666;
}
void Edit (int number)
{
bottles = number;
}
void Talk () const
{
std::cout << bottles << " bottles of beer of the wall" << std::endl;
}
};
class Bar
{
Foo foo;
void TrickEdit (int number)
{
// Because Foo::Edit is overloaded, we need to do some work:
using Method = void (Foo::*)(int);
Method ptr = &Foo::Edit;
ApplyMethod(foo, ptr, number);
}
void TrickTalk () const
{
// it's a lot neater when the method isn't overloaded:
ApplyMethod(foo, &Foo::Talk);
}
public:
void Trick ()
{
TrickEdit(900);
TrickTalk();
}
};
int main ()
{
Bar().Trick();
return 0;
}
I'm trying to perform the work at the function instead. The problem seems to lie in that &Foo::Edit has two different locations, depending on which Edit we're referring to.
In C++ FAQ - Pointers to member functions by Stroustrup and other reputable authors, I read:
Question: I need something like function-pointers, but with more flexibility and/or thread-safety; is there another way?
Answer: Use a functionoid.
Question: What the heck is a functionoid, and why would I use one?
Answer: Functionoids are functions on steroids. Functionoids are strictly more powerful than functions, and that extra power solves some (not all) of the challenges typically faced when you use function-pointers. [...] Functionoids don’t solve every problem encountered when making flexible software, but they are strictly more powerful than function-pointers and they are worth at least evaluating. In fact you can easily prove that functionoids don’t lose any power over function-pointers, since you can imagine that the old-fashioned approach of function-pointers is equivalent to having a global(!) functionoid object. Since you can always make a global functionoid object, you haven’t lost any ground. QED.
Given that the "power" of programming is basically the reduction of work duplication, and that with a normal function we would avoid the extra work at the call site that I've outlined in my problem, the FAQ answer implies that there should be a solution to this using functionoids. However, for the life of me, I can't see how functionoids would help in this case.
Maybe you can use something like that:
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
void Do(int,int) { std::cout << "Do 2 parms" << std::endl; }
};
template < typename OBJ_TYPE, typename ... ARGS >
auto Invoke( OBJ_TYPE&& obj, void( std::remove_reference<OBJ_TYPE>::type::* func)(ARGS...), ARGS&& ... args )
{
return std::invoke( func, obj, args... );
}
int main()
{
A a;
Invoke( a, &A::Do);
Invoke( a, &A::Do, 1);
Invoke( a, &A::Do,1,2);
}
The idea is simply to fix the pointer type of the member function pointer to the given arguments in the parameter pack.
If someone has an idea how to automatically determine the return type, so that we also can use overloads with different return types, that would be very funny! I end up in a recursion :-)
If we simply specify the return type, we can use it as follows:
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
int Do(int,int) { std::cout << "Do 2 parms" << std::endl; return 42;}
};
template < typename RETURN_TYPE, typename OBJ_TYPE, typename ... ARGS >
auto Invoke( OBJ_TYPE&& obj, RETURN_TYPE( std::remove_reference<OBJ_TYPE>::type::* func)(ARGS...), ARGS&& ... args )
{
return std::invoke( func, obj, args... );
}
int main()
{
A a;
Invoke<void>( a, &A::Do);
Invoke<void>( a, &A::Do, 1);
int retval = Invoke<int>( a, &A::Do,1,2);
std::cout << retval << std::endl;
}
You can write a variable template that specifies what Args... should be.
template <typename... Args>
struct Overload {
template<typename R, typename O>
operator R(O::*)(Args...) (R(O::*p)(Args...)) const { return p; }
template<typename R, typename O>
operator R(O::*)(Args...) const (R(O::*p)(Args...) const) const { return p; }
};
template <typename... Args>
Overload overload;
Which is used like
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
void Do(int,int) { std::cout << "Do 2 parms" << std::endl; }
};
template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
std::invoke(method, object, args...);
}
int main()
{
A a;
ApplyMethod( a, overload<>(&A::Do));
ApplyMethod( a, overload<int>(&A::Do), 1);
ApplyMethod( a, overload<int, int>(&A::Do),1,2);
}
This is what Qt does for it's modern signals and slots.
I'm new to C++ 14, I want to compose a variable length of lambda functions together to a single lambda, how should I do that? Below is my current work
#include <iostream>
template<typename Ftype>
Ftype compose(const Ftype & fn) {
return fn;
}
template<typename Ftype, typename... Other>
auto compose(Ftype fn, Other... other) {
return [=](auto x){return other(fn(x))...;};
} ➤ expression contains unexpanded parameter pack 'other'
int main(void) {
auto add_func = [](const int x) { return x * 7; };
auto sub_func = [](const int x) { return x + 1; };
int res = compose(add_func, sub_func)(1);
std::cout << "Result: " << res << "\n";
}
But I failed the compile, I guess I may use the lambda or variadic parameter somehow wrong.
Can someone help me?
Your "recursive" case contains no call to compose, that should be a hint of where you've mixed things up ;)
return [=](auto x){ return compose(other...)(fn(x)); };
Consider this simple example code:
#include <functional>
#include <iostream>
void f(bool _switch) {
std::cout << "Nothing really" << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
return 0;
}
It fails to compile:
$ g++ --std=c++11 main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:15:33: error: call of overloaded ‘f(main(int, char**)::<lambda(int)>)’ is ambiguous
main.cpp:15:33: note: candidates are:
main.cpp:6:6: note: void f(bool)
main.cpp:10:6: note: void f(std::function<double(int)>)
However if I replace the second function with a reference argument it compiles fine. And again if it is replaced by a const reference it fails.
So I have some questions concerning this example:
Why is a lambda function implicitly convertible to bool in the first place?
Why does taking a std::function reference solve the ambiguity?
And most important to me, how can I avoid this problem? I need the second function to take either a (copy of a) std::function or a const reference to it.
A lambda function with no capture can be converted to a regular function pointer, which then has a standard conversion to a bool.
If you take the std::function by non-const reference, then that eliminates it as a candidate, since converting the lambda to a std::function requires a temporary, and a temporary cannot bind to a non-const reference. That just leaves f(bool) as a candidate, so there is no ambiguity.
There are many ways you could avoid the ambiguity. For example, you could create a std::function variable first:
std::function<double(int)> g = [](int _idx){ return 7.9;};
f(g);
or you could cast the lambda:
f(std::function<double(int)>([](int _idx){return 7.9;}));
You could have a helper function:
template<typename T>
std::function<T> make_function(T *f) { return {f}; }
int main ( int argc, char* argv[] ) {
f(make_function([](int _idx){ return 7.9;}));
return 0;
}
or you could grab the particular function you are interested in:
int main ( int argc, char* argv[] ) {
void (*f_func)(std::function<double(int)>) = f;
f_func([](int _idx){ return 7.9;});
return 0;
}
namespace details{
template<class Sig,class=void>
struct invoke {};
template<class F, class...Args>
struct invoke<F(Args...),decltype(void(
std::declval<F>()(std::declval<Args>()...)
))>{
using type=decltype(std::declval<F>()(std::declval<Args>()...));
};
}
template<class Sig>struct invoke:details::invoke<Sig>{};
template<typename Sig, typename T, typename=void>
struct invoke_test:std::false_type {};
template<typename R, typename...Args, typename T>
struct invoke_test<R(Args...), T,
typename std::enable_if<
std::is_convertible<
typename invoke<T(Args...)>::type,
R
>::value
>::type
>:std::true_type {};
template<typename...Args,typename T>
struct invoke_test<void(Args...),T,
decltype( void( typename invoke<T(Args...)>::type ) )
>:std::true_type{};
template<typename Sig, typename T>
constexpr bool invokable() {
return invoke_test<Sig,T>::value;
}
this gives us a pseudo-concept invokable.
We can then use it like:
template<typename F>
typename std::enable_if<invokable<double(int),F>()>::type
f(F&&){
std::cout << "can be invoked\n";
}
void f(bool) {
std::cout << "is bool\n";
}
and bob is your uncle.
The real problem is that std::function<double(int)> 's constructor does not do a similar test, and instead claims (falsely) that it can be constructed from anything at all. This is a flaw in the standard, one I suspect will be fixed once concepts are standardized.
You can get rid of the implicit conversion by creating a helper class
#include <functional>
#include <iostream>
struct Boolean {
bool state;
Boolean(bool b):state(b){}
operator bool(){ return state; }
};
void f(Boolean _switch) {
std::cout << "Nothing really " << _switch << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
f(true);
return 0;
}
Should you ever want to call f with eg. a pointer and expect it to call the first overload you will have to cast it to either bool or add a corresponding constructor / cast to the helper class though.
One more option to Vaughn Cato's answer:
template<typename F>
void f(F _f) {
std::cout << "Nothing really, too: " << _f(3) << std::endl;
}
Now the second overload is a template, so it is chosen for a lambda (or anything), and the first is chosen for bool. So calling f is no more complex than needed.
But, one problem with that is if you want to add more overloads, and another is that the first overload will only be called if there is an exact match to bool.
Is it possible to declare a function bar to have the same signature as function foo?
int foo(int a)
{
return 0;
}
decltype(foo) bar
{
return 1;
} //imaginary syntax
I think the same applies as for typedefs and aliases: You may use decltype to declare a function, but not to define it:
int foo();
decltype(foo) bar;
int foo()
{
return bar();
}
int bar() { return 0; }
is accepted by clang++3.5 and g++4.8.1
[dcl.fct.def.general]/2 forbids (grammatically) the definition of a function w/o parentheses:
The declarator in a function-definition shall have the form
D1 ( parameter-declaration-clause ) cv-qualifier-seqopt
ref-qualifieropt exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt
as described in 8.3.5.
You can use variadic templates to define a function which has the same signature as any function:
#include <iostream>
int foo(char const *blah) { return 0; }
template<typename... Args>
auto bar(Args ... args) -> decltype(foo(args...))
{
return 1;
}
int main() {
std::cout << foo("test") << std::endl;
std::cout << bar("test") << std::endl;
return 0;
}
This could also be modified slightly to pass "foo" as the first template argument, so that you could use the same "bar" with many different "foo"s:
template<typename Func, typename... Args>
auto bar(Func f, Args ... args) -> decltype(f(args...))
{
return 1;
}
int baz(double d) { return 3; }
int main() {
std::cout << bar(&foo, "test") << std::endl;
std::cout << bar(&baz, 1.2) << std::endl;
return 0;
}
The first thing that comes into mind is that you need to name the parameters so no, you can't.
The type of foo is:
int(int)
so any imaginary declaration syntax like:
decltype(foo) bar { //imaginary syntax
// can't access parameter
return 1;
}
will have the problem that bar can't access parameters.
So the best you can do is what #dyp suggests.
One other thing you could do is to check if two functions have the same signature:
static_assert(std::is_same<decltype(foo), decltype(bar)>::value, "Invalid bar signature");
Not trivially as you're posing, since you cannot set the arguments directly. decltype(foo) does return the actual type of foo, so you can use that to instantiate a template traits class that then exposes the return type and arguments type (somehow), and then use that to define your function.
#include <stdio.h>
int sf(int, float, double, bool) {}
template <typename RV, typename... args>
RV func(args... as) {
printf("%d %f %f %d\n", as...);
return sf(as...);
}
template <typename RV, typename... args>
RV(*generateFunc(RV(*)(args...)))(args...) {
return &func<RV, args...>;
}
int main() {
decltype(sf) *f = generateFunc(sf);
f(42, 1.0f, 12.0, true);
}
This generates a function to match sf's signature and then forwards the call to it.