template<typename FirstArgT, typename...ArgsT>
class Server :public Server<ArgsT...> {
public:
Server(const function<void (FirstArgT, ArgsT...)>& func)
:Server<ArgsT...>([&](ArgsT args...) -> void { func(arg0, args...); }) { }
private:
FirstArgT arg0;
}
but the compiler says :
Error C3520 'ArgsT': parameter pack must be expanded in this context
Error C3546 '...': there are no parameter packs available to expand
in line 4 and 5.
Is it possible to use variadic parameters as parameters of a lambda is VS2015, or is there an alternative way to do it?
I extended and fixed your code to get it compiled. It would be nice if your next question comes with full example so that we have not the need to extend the rest of the example ;)
Indeed, I have no idea what you code is good for :-)
template<typename ...T> class Server;
template<typename FirstArgT, typename...ArgsT>
class Server<FirstArgT,ArgsT...> :public Server<ArgsT...> {
public:
Server(const std::function<void (FirstArgT, ArgsT...)>& func)
:Server<ArgsT...>([&](ArgsT ... args)-> void { func(arg0, args...); }) { }
private:
FirstArgT arg0;
};
template<typename FirstArgT>
class Server<FirstArgT>
{
public:
Server(const std::function<void (FirstArgT)>& func) {}
};
void Do( int, double) {}
int main()
{
Server<int,double> se( &Do );
}
If your intention is only to store the arguments somewhere and call the function with stored arguments, simply use std::bind.
void Do( int i, double d) { std::cout << i << " " << d << std::endl; }
int main()
{
auto fx= std::bind( &Do, 1, 2.34);
fx();
// which works also for lambda:
auto fx2=
std::bind( []( int i,double d )->void
{ std::cout << i << " " << d << std::endl; }, 4, 5.6);
}
Related
I have this minimal class to represent an event which client can subscribe to.
The event can have an data type associated to it, so when it is triggered by a publisher, an argument of that type would be passed to the client's callback:
template<typename Arg, typename Callback = function<void(const Arg&)>>
class Event
{
public:
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& arg) {
mCallback(arg);
}
private:
Callback mCallback;
};
Now I can create an Event<int> or any other concrete type, but it is really important to me to also allow "empty" event, which has no data associated with it: Event<void>
But sadly that doesn't work:
static void FooVoid() {
cout << "Look ma, no args!" << endl;
}
static void FooInt(int a) {
cout << "int arg " << a << endl;
}
int main()
{
/* Compiles */
Event<int> eInt(&FooInt);
eInt.Trigger(42);
/* Does not compile :(
Event<void> eVoid(&FooVoid);
eVoid.Trigger();
*/
return 0;
}
Is there any way to achieve this desired API? How?
(P.S the solution should work on C++11)
The quickest way of solving this without explicitly specializing for void is to use a parameter pack (added in C++11) for your template argument instead of a single type and using an empty parameter pack instead of void. A parameter pack can homogeneously hold any number of type, including 0 and 1. Then it can be used to generate the right types and member functions. You basically just have to add ... correctly near every use of Arg (link) :
#include <functional>
#include <iostream>
template<typename ... Arg>
class Event
{
public:
using Callback = std::function<void(const Arg&...)>;
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& ... arg) {
mCallback(arg...);
}
private:
Callback mCallback;
};
static void FooVoid() {
std::cout << "Look ma, no args!" << std::endl;
}
static void FooInt(int a) {
std::cout << "int arg " << a << std::endl;
}
int main()
{
/* Compiles */
Event<int> eInt(&FooInt);
eInt.Trigger(42);
Event<> eVoid(&FooVoid);
eVoid.Trigger();
return 0;
}
This has the added benefit that you can use callbacks with more than one argument. If this isn't desirable you can add a static_assert to prevent it :
template<typename ... Arg>
class Event
{
public:
using Callback = std::function<void(const Arg&...)>;
static_assert(sizeof...(Arg) <= 1, "Too many arguments");
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& ... arg) {
mCallback(arg...);
}
private:
Callback mCallback;
};
Notice that this solution requires Event<> instead of Event<void>. You can solve that by adding a short specialization for Event<void> that uses Event<> (link) :
template<>
class Event<void> : public Event<>
{
// Inherit constructors
using Event<>::Event;
};
I'm looking to write a class such than it can store a piece of data and pass it through a lambda. I'd also like to be able to have an option to not pass a value in the constructor and have the constructor generate with a lambda without a parameter. I'm OK, with still having a piece of data on the class.
I've tried using optionals and using a default template parameter of type void but couldn't get it to work. The closest thing I got was this.
template<class T = void>
class X {
std::optional<T> d; // data present or garbage data
std::function<void(T)> f; // parameter = type of data or void if no arg provided
public:
X(std::optional<T> a, std::function<void(T)> b) : d{a}, f{b} {}
a() {
if (d.has_value()) f(d);
else f();
}
}
Hoping the constructor work like
X(5, [&](int x) {}); // where the int type is implied from the constructor
OR
X([&](){}); // where the lack of parameter implies the function parameter is void
Thank you.
EDIT: provided an example of an attempt to generate the class myself
EDIT 2: attempted to clarified the need to store and call the function at a later date.
You can use something like this:
#include <iostream>
#include <functional>
void foo() {
std::cout << "void foo()" << std::endl;
}
void bar(int x) {
std::cout << "void foo(int x) with parameter x = " << x << std::endl;
}
class X {
public:
template <typename F, typename ... Args>
X(F&& f, Args&&... args) {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
};
int main() {
X a(foo);
X b(bar, 1);
X c([&](int x, int y) {
std::cout << "lambda with parameters x = " << x << " y = " << y << std::endl;
}, 1, 2);
return 0;
}
Check live
Basically, by using provided class X you can send whatever function you want (free function, lambda, etc.) and pass any number of parameters you want.
UPDATE
According to the OP's comment and wish to store the lambda and arguments to a class member and call it later, here is the updated code:
#include <iostream>
#include <tuple>
#include <functional>
template <typename F, typename ... Args>
class X {
public:
X(F&& f, Args&&... args)
: f_(std::forward<F>(f)),
args_(std::forward<Args>(args)...)
{}
void call() {
std::apply(f_, args_);
}
private:
F f_;
std::tuple<Args...> args_;
};
int main() {
X c([&](int x, int y) {
std::cout << "lambda with parameters x = " << x << " y = " << y << std::endl;
}, 1, 2);
c.call();
return 0;
}
Check live
Is this even possible?
#include <iostream>
#include <functional>
enum class Enum {a, b, c };
class Dispatch {
public:
void check(uint16_t) { std::cout << "check 16\n"; }
void check(uint32_t) { std::cout << "check 32\n"; }
void check(uint64_t) { std::cout << "check 64\n"; }
template<Enum E, typename... A>
void event(A&&... args) {
tag_event(Tag<E>(), std::forward<A>(args)...);
}
private:
template<Enum E> struct Tag {};
void tag_event(Tag<Enum::a>, uint16_t) { std::cout << "a\n"; }
void tag_event(Tag<Enum::b>, uint16_t) { std::cout << "b\n"; }
void tag_event(Tag<Enum::c>, uint16_t) { std::cout << "c\n"; }
};
void exec(std::function<void()>&& func) { func(); }
int main() {
Dispatch d;
// all good
exec(std::bind(static_cast<void(Dispatch::*)(uint16_t)>(&Dispatch::check), &d, uint16_t()));
exec(std::bind(static_cast<void(Dispatch::*)(uint32_t)>(&Dispatch::check), &d, uint32_t()));
exec(std::bind(static_cast<void(Dispatch::*)(uint64_t)>(&Dispatch::check), &d, uint64_t()));
// all good
d.event<Enum::a>(uint16_t());
d.event<Enum::b>(uint16_t());
d.event<Enum::c>(uint16_t());
// but how do we bind an event<> call?
exec(std::bind(static_cast<void(Dispatch::*)(uint16_t)>(&Dispatch::event<Enum::a>), &d, uint16_t()));
}
So I'm trying to bind a call to the variadic template method but get the following compiler error...
In function 'int main()':
42:86: error: no matches converting function 'event' to type 'void (class Dispatch::*)(uint16_t) {aka void (class Dispatch::*)(short unsigned int)}'
13:10: note: candidate is: template<Enum E, class ... A> void Dispatch::event(A&& ...)
Any suggestions short of exposing all the tag overloads instead?
I suggest to pass through a lambda function, as suggested in comments.
Anyway, if you want to pass to std::bind(), seems to me that a possible solution is
// ..................................................VVVVVVVV <-- ad this
exec(std::bind(static_cast<void(Dispatch::*)(uint16_t const &)>
(&Dispatch::event<Enum::a, uint16_t const &>), &d, uint16_t()));
// ...........................^^^^^^^^^^^^^^^^^^ <-- and this
I mean: you have to select the event() method explicating also the received type; I suggest uint16_t const & (instead of uint16_t) that is compatible with universal reference signature of your event() method (I suppose other combinations are possible but for a uint16_t activate move semantics... I suppose it's superfluous).
I'd like to create a class, than when instantiated, accepts a variable number of function references that don't have signatures known beforehand. Here's an example that almost does what I want:
// To show the function refs being used
void p(int arg) { cout << "int " << arg << endl; }
void p(string arg) { cout << "string " << arg << endl; }
void p(int arg1, int arg2) { cout<<"int/int "<<arg1<<arg2<<endl; }
void p(int arg1, string arg2) { cout<<"int/string "<<arg1<<arg2<<endl; }
class foo {
public:
// CTOR takes variadic function refs
template <typename... Args>
foo(Args... args) { p(args()...); }
// "args()..." requires supplied functions to take no parameters
// but makes no requirement on their return values.
};
// Using lambdas, but free functions, std::bind(), etc. work too
foo i([]{return 1;}); // prints "int 1"
foo s([]{return string("one");}); // prints "string one"
foo b([]{return 2;},
[]{return string("two");}); // prints "int/string 2two"
What I can't see how to fix this so that the functions supplied as arguments are not evaluated in the constructor. I'd like the call to p(args()...) to be done later, by another method in foo. This is why foo can't be created as simply as foo i(1): the argument function(s) need to be called later, and multiple times, not just once when the object is created (and they'd be more complex than just returning a constant).
The problem seems to come down to saving references to the constructor parameters to be called later, when the class doesn't know how many or what signature those parameters will have. Somehow the arguments need to be part of a class template and not just a constructor template, but how?
If the functions passed all had the same signature, then one could use a class template with a non-type parameters and supply the functions as template arguments:
template <int (&...Arg)()>
class bar {
public:
bar() { p(Arg()...); }
other() { p(Arg()...); } // Use in any method
};
int one() { return 1; }
int two() { return 2; }
bar<one> bi; // Prints "int 1"
bar<one, two> bii; // Prints "int/int 12"
But this requires all the arguments be functions that return int and also doesn't work with lambdas as they can't be template arguments.
You can use a lambda and a std::function to do that.
Note that a lambda can capture a parameters pack and (let me say) unpack it later.
It follows a minimal, working example:
#include<iostream>
#include<functional>
void p(int arg) { std::cout << "int " << arg << std::endl; }
void p(std::string arg) { std::cout << "string " << arg << std::endl; }
void p(int arg1, int arg2) { std::cout<<"int/int "<<arg1<<arg2<<std::endl; }
void p(int arg1, std::string arg2) { std::cout<<"int/string "<<arg1<<arg2<<std::endl; }
class foo {
public:
template <typename... Args>
foo(Args... args): func{[args...](){ p(args()...); }} {}
void operator()() { func(); }
private:
std::function<void()> func;
};
int main() {
// create your objects...
foo i([]{return 1;});
foo s([]{return std::string("one");});
foo b([]{return 2;}, []{return std::string("two");});
// ... and use them later
i();
s();
b();
}
I have a method like this
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, T (f)(T,U))
{
map<T,U> new;
for(auto it = old.begin(); it != old.end(); ++it)
{
new[it->first] = f(it->first,it->second);
}
return new;
}
and the idea is that you'd call it like this
BOOST_AUTO_TEST_CASE(MapMapValues_basic)
{
map<int,int> test;
test[1] = 1;
map<int,int> transformedMap = VlcFunctional::mapMapValues(test,
[&](int key, int value) -> int
{
return key + 1;
}
);
}
However I get the error: no instance of function template "VlcFunctional::mapMapValues" matches the argument list argument types are: (std::map, std::allocator>>, __lambda1)
Any idea what I'm doing wrong? Visual Studio 2008 and Intel C++ compiler 11.1
Your function is expecting a function pointer, not a lambda.
In C++, there are, in general, 3 types of "callable objects".
Function pointers.
Function objects.
Lambda functions.
If you want to be able to use all of these in your function interface, then you could use std::function:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T, U)> f)
{
...
}
This will allow the function to be called using any of the three types of callable objects above. However, the price for this convenience is a small amount of overhead on invokations on the function (usually a null pointer check, then a call through a function pointer). This means that the function is almost certainly not inlined (except maybe with advanced WPO/LTO).
Alternatively, you could add an additional template parameter to take an arbitrary type for the second parameter. This will be more efficient, but you lose type-safety on the function used, and could lead to more code bloat.
template<typename T, typename U, typename F>
map<T,U> mapMapValues(map<T,U> old, F f)
Your parameter type declaration T (f)(T,U) is of type 'free function taking a T and a U and returning a T'. You can't pass it a lambda, a function object, or anything except an actual function with that signature.
You could solve this by changing the type of the parameter to std::function<T(T,U)> like this:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T,U)>)
{
}
Alternately, you could declare the function type as a template argument like this:
template<typename T, typename U, typename Fn>
map<T,U> mapMapValues(map<T,U> old, Fn fn)
{
fn(...);
}
I would like to contribute this simple but self-explanatory example. It shows how to pass "callable things" (functions, function objects, and lambdas) to a function or to an object.
// g++ -std=c++11 thisFile.cpp
#include <iostream>
#include <thread>
using namespace std;
// -----------------------------------------------------------------
class Box {
public:
function<void(string)> theFunction;
bool funValid;
Box () : funValid (false) { }
void setFun (function<void(string)> f) {
theFunction = f;
funValid = true;
}
void callIt () {
if ( ! funValid ) return;
theFunction (" hello from Box ");
}
}; // class
// -----------------------------------------------------------------
class FunClass {
public:
string msg;
FunClass (string m) : msg (m) { }
void operator() (string s) {
cout << msg << s << endl;
}
};
// -----------------------------------------------------------------
void f (string s) {
cout << s << endl;
} // ()
// -----------------------------------------------------------------
void call_it ( void (*pf) (string) ) {
pf( "call_it: hello");
} // ()
// -----------------------------------------------------------------
void call_it1 ( function<void(string)> pf ) {
pf( "call_it1: hello");
} // ()
// -----------------------------------------------------------------
int main() {
int a = 1234;
FunClass fc ( " christmas ");
f("hello");
call_it ( f );
call_it1 ( f );
// conversion ERROR: call_it ( [&] (string s) -> void { cout << s << a << endl; } );
call_it1 ( [&] (string s) -> void { cout << s << a << endl; } );
Box ca;
ca.callIt ();
ca.setFun (f);
ca.callIt ();
ca.setFun ( [&] (string s) -> void { cout << s << a << endl; } );
ca.callIt ();
ca.setFun (fc);
ca.callIt ();
} // ()
Lambda expressions with empty capture list should decay to function pointers, according to n3052. However it seems that this feature is not implemented in VC++ and only partially in g++, see my SO question.
Here is some example of how to pass a function as parameter
class YourClass
{
void YourClass::callback(void(*fptr)(int p1, int p2))
{
if(fptr != NULL)
fptr(p1, p2);
}
};
void dummyfunction(int p1, int p2)
{
cout << "inside dummyfunction " << endl;
}
YourClass yc;
// using a dummyfunction as callback
yc.callback(&dummyfunction);
// using a lambda as callback
yc.callback( [&](int p1, int p2) { cout << "inside lambda callback function" << endl; } );
// using a static member function
yc.callback( &aClass::memberfunction );