This question already has answers here:
Is auto as a parameter in a regular function a GCC 4.9 extension?
(2 answers)
Closed 5 years ago.
I want to declare a function that takes as argument a function (or lambda) with a specific prototype.
The first try is:
#include <iostream>
using namespace std;
int test(int (&val)(int)) {
return val(2);
}
int main() {
cout << test([](int v){
return v+100;
});
return 0;
}
witch results in error: invalid initialization of non-const reference of type 'int (&)(int)' from an rvalue of type 'main()::<lambda(int)>'
I tried to add const specified to the type but I don't know where exactly so I tried the following that works with GCC (-std=c++14), however I suspect it is illegal since it fails with clang:
int test(const auto& val) {
return val(2);
}
I know I can use template or function pointers or std::function to achieve the same, then please consider this a didactic question. I want to know what does GCC deduce the type of val to, in the second example above (int test(const auto& val)).
template <typename F>
int test(F val) {
return val(2);
}
int test(int val(int)) {
return val(2);
}
int test(std::function<int(int)> val) {
return val(2);
}
I want to declare a function that takes as argument a function (or lambda) with a specific prototype.
Closures generated by lambda expression have a unique and anonymous type. They could also be generic (i.e. template operator()). There is no "easy" way of declaring a function accepting lambdas with a specific prototype. Your best bet is either using a constrained template parameter with something like std::is_invocable or using some sort of type erasure like function_view.
Note: if your lambda is captureless it is implicitly convertible to a function pointer. E.g.
int test(int (*)(int)) { }
test([](int) -> int {}); // OK
test([i = 0](int) -> int {}); // compile-time error
I want to know what does GCC deduce the type of val to, in the second example.
int test(int val(int))
...is equivalent to...
int test(int (*val)(int))
In fact, having both of them in the same scope results in a redefinition error:
int test(int val(int)) {
return val(2);
}
int test(int (*val)(int)) {
return val(2);
}
prog.cc:5:5: error: redefinition of 'test'
int test(int (*val)(int)) {
^
prog.cc:1:5: note: previous definition is here
int test(int val(int)) {
^
Related
This question already has answers here:
Is there any way in C++ to refer to a function template while neither calling it nor supplying its template parameters?
(4 answers)
Convert template function to generic lambda
(2 answers)
How do I make a functor out of an arbitrary function?
(2 answers)
Closed 2 years ago.
I have a function returning a std::pair, which I want to use to call an overloaded member function. I am not aware of any way to unpack a tuple in-place (which I'd prefer), so std::apply is my best bet, I think.
This works with a combination of tuple_cat and forward_as_tuple when the member function is not overloaded, but otherwise, the compiler complains about an unresolved overload.
That is understandable, given that std::apply just takes a function pointer, but I'd still like to know whether it can be made to work in a readable way.
Here's some example code:
#include <iostream>
#include <tuple>
#include <utility>
std::pair<int, int> func() { return { 0, 1 }; }
class MyClass {
public:
int memFun(int);
int memFun(int, int);
};
int MyClass::memFun(int i){ return 2*i; }
int MyClass::memFun(int a, int b){ return a+b; }
int main(){
MyClass myClass;
/* works */
std::pair pair { func() };
int number { myClass.memFun( pair.first, pair.second ) };
/* doesn't work (unresolved overload) */
int number { std::apply(
&MyClass::memFun,
std::tuple_cat( std::forward_as_tuple(myClass), func() )
) };
std::cout << number << "\n";
return 0;
}
Is there an elegant (=readable) way to do this without a temporary?
I only found this question and so far don't think it fully applies.
I'd like to create a class where the client can store a lambda expression like []() -> void {} as a field of the class, but I can't figure out how to do so. One answer suggested using decltype, which I tried with no success. Here is a ideone source link. The below is the source and result:
#include <cstdio>
auto voidLambda = []()->void{};
class MyClass {
public:
decltype(voidLambda) t;
MyClass(decltype(voidLambda) t) {
this->t = t;
}
};
int main() {
MyClass([] {
printf("hi");
});
}
Result:
prog.cpp: In constructor 'MyClass::MyClass(<lambda()>)':
prog.cpp:3:79: error: no matching function for call to '<lambda()>::__lambda0()'
prog.cpp:2:20: note: candidates are: <lambda()>::<lambda>(const<lambda()>&)
prog.cpp:2:20: note: <lambda()>::<lambda>(<lambda()>&&)
prog.cpp:3:88: error: no match for 'operator=' in '((MyClass*)this)->MyClass::t = t'
prog.cpp: In function 'int main()':
prog.cpp:5:27: error: no matching function for call to 'MyClass::MyClass(main()::<lambda()>)'
prog.cpp:3:48: note: candidates are: MyClass::MyClass(<lambda()>)
prog.cpp:3:14: note: MyClass::MyClass(const MyClass&)
Does anyone know how to do this?
If you want a class member to be a lambda expression, consider using the std::function<> wrapper type (from the <functional> header), which can hold any callable function. For example:
std::function<int()> myFunction = [] { return 0; }
myFunction(); // Returns 0;
This way, you don't need to know the type of the lambda expression. You can just store a std::function<> of the appropriate function type, and the template system will handle all the types for you. More generally, any callable entity of the appropriate signature can be assigned to a std::function<>, even if the the actual type of that functor is anonymous (in the case of lambdas) or really complicated.
The type inside of the std::function template should be the function type corresponding to the function you'd like to store. So, for example, to store a function that takes in two ints and returns void, you'd make a std::function<void (int, int)>. For a function that takes no parameters and returns an int, you'd use std::function<int()>. In your case, since you want a function that takes no parameters and returns void, you'd want something like this:
class MyClass {
public:
std::function<void()> function;
MyClass(std::function<void()> f) : function(f) {
// Handled in initializer list
}
};
int main() {
MyClass([] {
printf("hi")
}) mc; // Should be just fine.
}
Hope this helps!
The only way I can think of to store a lambda in a class is to use a template with a helper make_ function:
#include <cstdio>
#include <utility>
template<class Lambda>
class MyClass {
Lambda _t;
public:
MyClass(Lambda &&t) : _t(std::forward<Lambda>(t)) {
_t();
}
};
template<class Lambda>
MyClass<Lambda> make_myclass(Lambda &&t) {
return { std::forward<Lambda>(t) };
}
int main() {
make_myclass([] {
printf("hi");
});
}
In case of [] (empty capture) simple function pointer can be used. Declaration syntax is ReturnType (*pointer_name) (Arg1T, Arg2T); for pointer, ReturnType (&ref_name) (/*void*/); for reference (can't be null). Lambda with empty capture block is implicitly convertible to function pointer with same signature. And std::function have runtime and size (it is at least three times larger) overhead.
struct S
{
void (*f_p)() {}; // `{}` means `= nullptr`;
};
int main()
{
S s { [] { std::cout << "Lambda called\n"; }};
s.f_p();
S s2;
if (s2.f_p) // check for null
s.f_p();
s2.f_p = [] { std::cout << "Lambda2 called\n"; };
s2.f_p();
s2.f_p = std::terminate; // you can use regular functions too
s2.f_p();
}
Output
Lambda called
Lambda2 called
terminate called without an active exception
class A {
int f(int x, int j) { return 2;}
decltype(f)* p;
};
Gives me the error:
error: decltype cannot resolve address of overloaded function
I can't understand why that error is even speaking of overloaded functions. Similarly I thought that maybe I needed to use the scope operator to access the function:
class A {
int f(int x, int j) { return 2;}
decltype(A::f)* p;
};
Which still gives me an error but a clearer description:
error: invalid use of non-static member function 'int A::f(int, int)'
Why is it that I'm not allowed to use decltype to find the type of a member function? Alternatively setting the member function to static removes the error in either case.
What you really want is:
struct a {
int f(int x, int j) { return 2;}
decltype(&a::f) p;
};
Live demo
Since the f you are referring to is a member function. The deduced type is:
int(a::*)(int, int)
Without the & the compiler is assuming that you are trying to call the function without providing arguments to it. Perhaps Clang's error message is clearer about this:
error: call to non-static member function without an object argument
decltype(a::f) p;
If you really don't want the pointer type you can later apply std::remove_pointer_t from <type_traits>.
8.3.5/8 Functions [dcl.fct] says
[...] Functions shall not have a return type of
type array or function, although they may have a return type of type pointer or reference to such things. [...]
Why so explicit of a rule? Is there some syntax that would even allow returning a function as opposed to a function pointer?
Am I miss-interpreting the quote?
typedef void (*fp)();
void foo(){}
fp goo()
{
return foo; //automatically converted to function pointer
}
This is quite a contrived example of a function trying to return a function:
void foo() { }
template<typename T>
T f() { return foo; }
int main(){
f<decltype(foo)>();
}
This is the error I get from Clang 3.2:
Compilation finished with errors:
source.cpp:7:5: error: no matching function for call to 'f'
f<decltype(foo)>();
^~~~~~~~~~~~~~~~
source.cpp:4:3: note: candidate template ignored: substitution failure
[with T = void ()]: function cannot return function type 'void ()'
T f() { return foo; }
~ ^
1 error generated.
Is there some syntax that would even allow returning a function as opposed to a function pointer?
A syntax? Sure there is:
using fun = int (int);
fun function_that_returns_a_function();
That doesn’t compile because the rule in §8.3.5/8 forbids it. I don’t know why the rule specifically exists – but consider that the type “function” doesn’t have any size so you cannot create objects of function type in C++.
I know this probably does not answer your question completely but it does so partially
You can return a function from another function (that's what lambdas are)
std::function<int (int)> retLambda() {
return [](int x) { return x; };
}
I came across a strange situation today where I needed a function to not implicitly convert values.
After some looking on google I found this http://www.devx.com/cplus/10MinuteSolution/37078/1954
But I thought it was a bit stupid to use a function overload for every other type I want to block so instead I did this.
void function(int& ints_only_please){}
int main()
{
char a=0;
int b=0;
function(a);
function(b);
}
I showed the code to a friend and he suggested I added const before int so the variable isn't editable, however when I did started compiling fine but it shouldn't, look below to see what I mean
void function(const int& ints_only_please){}
int main()
{
char a=0;
int b=0;
function(a); //Compiler should stop here but it doesn't with const int
function(b);
}
Does anyone know why this is?
Use templates to get the desired effect:
template <class T>
void foo(const T& t);
template <>
void foo<int>(const int& t)
{
}
int main(){
foo(9); // will compile
foo(9.0); // will not compile
return 0;
}
Note that we only write a special version of the template for int so that a call that has any other type as a template parameter will result in a compile error.
It is legal to bind a temporary to a const reference, but not a non-const reference.
A char can be implicitly converted to an int and the temporary that is the result of this conversion can be bound to a const int& function parameter extending the temporary's lifetime until the function exits.