I'm trying to pass a function, with a variable amount of parameters, as an argument to my function baz(). I'm not really sure how to go about doing this, but hopefully the example I've provided below shows my current thought-process.
#include <iostream>
template<typename... Ts>
void foo(void (*func)(Ts...)){
func(Ts...);
}
void bar(int a, int b, std::string c){
std::cout << "Test a: " << a << " Test b: " << b << " Test c: " << c << "\n";
}
void baz(int x, int y){
std::cout << x+y << "\n";
}
int main()
{
foo(&bar, 10, 20, "Hello!"); // Expected: "Test a: 10 Test b: 20 Test c: Hello!"
foo(&baz, 2, 2); // Expected: "4"
// main.cpp:13:12: error: expected primary-expression before ‘...’ token
return 0;
}
Any help is greatly appreciated.
You can pass a function type
#include <iostream>
template<typename Fn, typename ... Ts>
void foo( Fn&& func, Ts...ts ){
func(ts...);
}
void bar(int a, int b, std::string c){
std::cout << "Test a: " << a << " Test b: " << b << " Test c: " << c << "\n";
}
void baz(int x, int y){
std::cout << x+y << "\n";
}
int main()
{
foo(&bar, 10, 20, "Hello!"); // Expected: "Test a: 10 Test b: 20 Test c: Hello!"
foo(&baz, 2, 2); // Expected: "4"
return 0;
}
Produces
Program stdout
Test a: 10 Test b: 20 Test c: Hello!
4
Godbolt: https://godbolt.org/z/beMv6a9a4
Or you can slightly alter your approach and instead of passing the args yourself you can let a lambda capture them.
#include <iostream>
#include <type_traits>
// you can call foo with any invocable
// and even let it return the return value of that invocable.
template<typename fn_t>
auto foo(fn_t&& fn ) -> std::enable_if_t<std::is_invocable_v<fn_t>, decltype(fn())>
{
std::cout << "foo begin\n";
// slightly different handling for functions returning a void
if constexpr (std::is_same_v<decltype(fn()), void>)
{
fn();
std::cout << "foo end\n";
}
else
{
auto retval = fn();
std::cout << "foo end\n";
return retval;
}
}
void bar(int a, int b, std::string c)
{
std::cout << "Test a: " << a << " Test b: " << b << " Test c: " << c << "\n";
}
int baz(int x, int y)
{
std::cout << x + y << "\n";
return x + y;
}
int main()
{
int x{ 2 };
int y{ 3 };
foo([&] { bar(x, y, "Hello!"); } );
int sum = foo([&] { return baz(x,y); });
return sum;
}
Related
I wish to use std::function type from so that function signature is checked on assignment. But I fail to understand what is happening in this case
//g++ 5.4.0
#include <iostream>
#include <functional>
int f(int x) { std::cout << "//f:int->int\n"; return x; }
int g(double x) { std::cout << "//g:double->int\n"; return 1; }
int main()
{
std::function<int(int)> fct;
fct = f; fct(1);
fct = g; fct(1);
}
//trace
//
//f:int->int
//g:double->int
The behavior for f is what I want, but I thought that "fct=g;" would cause a compile time error.
Any light on this case please ?
std::function accepts any callable that where the parameters can be converted and the return type is convertible. If they aren't you get a compilation error. For instance:
int h(double& x);
std::function<int(int)> fct;
fct = h; // <- compiler error
std::function is flexible and uses type erasure underneath, so if you have std::function object with with signature std::function<R(Args...)>, it will accept any Callable that can be called with type Args... and returns type R,
So in your case for std::function<int(int)>, function of type int g(double); can be called with type int arguments compiler will just promote int to double,
If you run this code
#include <iostream>
#include <functional>
int f(int x) { std::cout << x << " " << "//f:int->int\n"; return x; }
int g(double x) { std::cout << x << " " << "//g:double->int\n"; return 1; }
int main()
{
std::function<int(int)> fct;
fct = f; fct(1);
fct = g; fct(2.5);
}
You can see that fct will only accept int and afterwards compiler promote it to double, So In the output of fct(2.5); it will print 2 //g:double->int and not 2.5 //g:double->int
to complete the answer from #gaurav, complete scenarii using implicit conversion (it did surprise me, so I add it for anyone interested)
//g++ 5.4.0
#include <iostream>
#include <functional>
class C{
public :
int i;
C(int _i) : i(_i) { std::cout << "//C::C(int " << i << ")\n"; }
};
class D{
public :
int i;
D(int _i) : i(_i) { std::cout << "//D::D(int " << i << ")\n"; }
D(C c) : i(c.i) { std::cout << "//implicit conversion D::D(C " << c.i << ")\n"; }
};
int f(C c) { std::cout << "//f:C->int : "; return c.i; }
int g(D d) { std::cout << "//g:D->int : "; return d.i; }
int main()
{
{
std::cout << "//--- test implicit conversion\n";
C c(1);
D d(2);
d=c;
}
{
std::function<int(C)> fct; C c(1); D d(2);
std::cout << "//direct calls\n";
std::cout << f(c) << "\n";
// std::cout << "//" << f(d) << "\n"; // no conversion D->C provided by class C -->> error: could not convert ‘d’ from ‘D’ to ‘C’
std::cout << g(d) << "\n";
std::cout << g(c) << "\n"; // implicit conversion, then g:D->int
}
{
std::cout << "//case function:C->int\n";
std::function<int(C)> fct; C c(1); D d(2);
fct = f; std::cout << "//" << fct(c) << "\n";
//std::cout << "//" << fct(d) << "\n"; // no conversion D->C provided by class C -->> error: could not convert ‘d’ from ‘D’ to ‘C’
fct = g; std::cout << "//" << fct(c) << "\n";
//std::cout << "//" << fct(d) << "\n"; // no conversion D->C provided by class C -->> no match for call to ‘(std::function<int(C)>) (D&)’
}
{
std::cout << "//appels via function : D -> int\n";
std::function<int(D)> fct; C c(1); D d(2);
//fct = f; // conversion D->C would be meaningless to f
// -->> error: no match for ‘operator=’ (operand types are ‘std::function<int(D)>’ and ‘int(C)’)
fct = g; std::cout << "//" << fct(d) << "\n";
std::cout << "//" << fct(c) << "\n"; // implicit conversion, then g:D->int
}
}
//trace
//
//--- test implicit conversion
//C::C(int 1)
//D::D(int 2)
//implicit conversion D::D(C 1)
//C::C(int 1)
//D::D(int 2)
//direct calls
//f:C->int : 1
//g:D->int : 2
//implicit conversion D::D(C 1)
//g:D->int : 1
//case function:C->int
//C::C(int 1)
//D::D(int 2)
//f:C->int : //1
//implicit conversion D::D(C 1)
//g:D->int : //1
//appels via function : D -> int
//C::C(int 1)
//D::D(int 2)
//g:D->int : //2
//implicit conversion D::D(C 1)
//g:D->int : //1
I want to make a function that can wrap any lambda to log start/end calls on it.
The code below works except for:
any lambda that has captures
any lambda that returns void (although this can easily be fixed by writing a second function)
#include <iostream>
#include <functional>
template <class T, class... Inputs>
auto logLambda(T lambda) {
return [&lambda](Inputs...inputs) {
std::cout << "STARTING " << std::endl;
auto result = lambda(inputs...);
std::cout << "END " << std::endl;
return result;
};
}
int main() {
int a = 1;
int b = 2;
// works
auto simple = []() -> int {
std::cout << "Hello" << std::endl; return 1;
};
logLambda(simple)();
// works so long as explicit type is declared
auto with_args = [](int a, int b) -> int {
std::cout << "A: " << a << " B: " << b << std::endl;
return 1;
};
logLambda<int(int, int), int, int>(with_args)(a, b);
// Does not work
// error: no matching function for call to ‘logLambda<int(int), int>(main()::<lambda(int)>&)’
auto with_captures = [&a](int b) -> int {
std::cout << "A: " << a << " B: " << b << std::endl;
return 1;
};
logLambda<int(int), int>(with_captures)(b);
}
Is there any way to do this? Macros are also acceptable
Use Raii to handle both void and non-void return type,
and capture functor by value to avoid dangling reference,
and use generic lambda to avoid to have to specify argument your self
It results something like:
template <class F>
auto logLambda(F f) {
return [f](auto... args) -> decltype(f(args...)) {
struct RAII {
RAII() { std::cout << "STARTING " << std::endl; }
~RAII() { std::cout << "END " << std::endl; }
} raii;
return f(args...);
};
}
Call look like:
const char* hello = "Hello";
logLambda([=](const char* s){ std::cout << hello << " " << s << std::endl; })("world");
Demo
That code has undefined behavior.
auto logLambda(T lambda) {
return [&lambda]
You are capturing local parameter by reference.
I have class A which has methods void fun(int, int) and void fun1(int, int). These are non-static methods.
struct A {
void fun(int,int){}
void fun1(int,int){}
};
Now inside class B I want to store pointer to one of the method.
Which means object1 of B will have pointer to fun and object2 of B will have pointer to fun1.
Now my set_handler() and pointer to handler has to be generic.
One way is to use function pointers.
So that that I can use void(A::*pointer)(int,int) which can store address of fun or fun1.
struct B {
typedef void(A::*pointer)(int,int);
pointer f;
void set_handler(pointer p) { f = p; }
};
int main() {
{
B object1;
object2.set_handler(&A::fun);
}
{
B object2;
object2.set_handler(&A::fun1);
}
}
I was looking into boost::bind() but it needs specific name. How do I use boost here?
I malled your question into running code that actually does something with the pointer - so we know when the goal has been achieved:
Live On Coliru
#include <iostream>
struct A {
void fun(int a, int b) { std::cout << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
void fun1(int a, int b) { std::cout << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
};
struct B {
typedef void (A::*pointer)(int, int);
pointer f;
void set_handler(pointer p) { f = p; }
void run(A& instance) {
(instance.*f)(42, 42);
}
};
int main() {
B object1;
B object2;
object1.set_handler(&A::fun);
object2.set_handler(&A::fun1);
A a;
object1.run(a);
object2.run(a);
}
Prints
fun(42,42)
fun1(42,42)
Using boost::function or std::function
You have to allow for the instance argument (the implicit this parameter):
Live On Coliru
struct B {
using function = std::function<void(A&, int, int)>;
function f;
void set_handler(function p) { f = p; }
void run(A& instance) {
f(instance, 42, 42);
}
};
Which prints the same output. Of course you can use boost::function and boost::bind just the same
What about bind?
Bind comes in when you want to adapt the function signatures. So, e.g. you want to bind to any instance of A& without actually passing it into run():
Live On Coliru
#include <iostream>
#include <functional>
struct A {
std::string name;
void fun(int a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
void fun1(int a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
};
struct B {
using function = std::function<void(int, int)>;
function f;
void set_handler(function p) { f = p; }
void run() {
f(42, 42);
}
};
int main() {
B object1;
B object2;
A a1 {"black"};
A a2 {"white"};
{
using namespace std::placeholders;
object1.set_handler(std::bind(&A::fun, &a1, _1, _2));
object2.set_handler(std::bind(&A::fun1, &a2, _1, _2));
}
object1.run();
object2.run();
}
Which prints:
name:black fun(42,42)
name:white fun1(42,42)
More Goodness
From c++ you can do without bind and its pesky placeholders (there are other caveats, like bind storing all arguments by value). Instead, you may use lambdas:
Live On Coliru
#include <iostream>
#include <functional>
struct A {
std::string name;
void fun(int a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
void fun1(int a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
};
struct B {
using function = std::function<void(int, int)>;
function f;
void set_handler(function p) { f = p; }
void run() {
f(42, 42);
}
};
int main() {
B object1;
B object2;
object1.set_handler([](int a, int b) {
A local_instance {"local"};
local_instance.fun(a*2, b*3); // can even do extra logic here
});
A main_instance {"main"};
object2.set_handler([&main_instance](int a, int b) {
main_instance.fun1(a, b); // can even do extra logic here
});
object1.run();
object2.run();
}
Prints
name:local fun(84,126)
name:main fun1(42,42)
# pass by value
#include "stdafx.h"
#include <functional>
#include <iostream>
#include <string>
std::function<void(int)> Foo(int v)
{
auto l = [v](int i)
{
std::cout << v << " " << i << std::endl;
};
return l;
}
int main()
{
//[](int e, int f) {std::cout << e << f; }(5, 6);
[](int a, int b)
{
return [=](int c, int d)
{
int a1 = a, a2 = b, a3 = c, a4 = d;
std::cout << a << " " << b << std::endl << c << " " << d << std::endl;
};
}(2, 3)(4, 5);
}
# pass by reference
#include "stdafx.h"
#include <functional>
#include <iostream>
#include <string>
std::function<void(int)> Foo(int v)
{
auto l = [v](int i)
{
std::cout << v << " " << i << std::endl;
};
return l;
}
int main()
{
//[](int e, int f) {std::cout << e << f; }(5, 6);
[](int a, int b)
{
return [&](int c, int d)
{
int a1 = a, a2 = b, a3 = c, a4 = d;
std::cout << a << " " << b << std::endl << c << " " << d << std::endl;
};
}(2, 3)(4, 5);
}
my question is when I pass references, why the output is not the same as passing values?
mingw also has different values with reference-passing:
4 5
4 5
when I learn the little schemer, I try convert codes in the book to c++, then come up with the question.
a and b are dangling references at the point of call.
I am trying to understand template specialization in C++. I have read other forums, but cannot get it working in practice. I am trying to learn with a very simple example which I will explain.
What I would like to accomplish: I want foo to exhibit different behaviors based on the type. The code below does not work, but I have commented the behavior I would like to see. Could someone please fill in the lines that I commented. Please let me know if anything is unclear.
#include <iostream>
#include <string>
template <typename T>
class my_template
{
public:
foo() {return 0} // default behavior if there does not exist foo() function for the specified type
};
template <>
class my_template<int>
{
public:
// implement foo function: should return -1 if the type = int
};
template <>
class my_template<long>
{
public:
// implement foo function: should return 100 if the type = long
};
int main()
{
my_template<int> x;
my_template<long> y;
my_template<double> z;
std::cout << x.foo() << "\n"; // print -1
std::cout << y.foo() << "\n"; // print 100
std::cout << z.foo() << "\n"; // print 0
return 0;
}
Just to show you a few different approaches.
If you use a metafunction approach, then nothing will ever be done at run-time (guaranteed):
template<typename>
struct my_template{
enum { value = 0 };
};
template<>
struct my_template<int>{
enum { value = -1 };
};
template<>
struct my_template<long>{
enum { value = 100 };
};
int main(){
std::cout << "float: " << my_template<float>::value << '\n';
std::cout << "int: " << my_template<int>::value << '\n';
std::cout << "long: " << my_template<long>::value << '\n';
}
Or you could use a template variable ( C++14 ):
template<typename>
constexpr int my_value = 0;
template<>
constexpr int my_value<int> = -1;
template<>
constexpr int my_value<long> = 100;
int main(){
std::cout << "float: " << my_value<float> << '\n';
std::cout << "int: " << my_value<int> << '\n';
std::cout << "long: " << my_value<long> << '\n';
}
Or use a template function:
template<typename T>
int func_impl(T){ return 0; }
int func_impl(int){ return -1; }
int func_impl(long){ return 100; }
template<typename T>
int func(){
return func_impl(T(0));
}
int main(){
std::cout << "float: " << func<float>() << '\n';
std::cout << "int: " << func<int>() << '\n';
std::cout << "long: " << func<long>() << '\n';
}
template <typename T>
class my_template
{
public:
int foo() {return 0;} // default behavior
};
template <>
class my_template<int>
{
public:
int foo() {return -1;}
};
Is that enough?