Check validity of std::function before calling? - c++

I'm trying to program a simple but flexible event system (mostly just as an exercise, I know there are existing libraries that have really good event handlers), and I've run into a little stumbling block.
How can you check if an std::function that's a delegate (probably through a lambda, possibly though std::bind) is a valid function/if the object for the member function still exists before calling it? I've tried simply using std::function's bool operator, but haven't had any success.
Ideally I'd like to A. do the checking somewhere other than inside the delegate function, and B. still have the code be valid when the std::function that's being checked isn't a delegate.
Any ideas?
Edit: Here's the source for the test that I ran
#include <iostream>
#include <string>
#include <functional>
class Obj {
public:
std::string foo;
Obj(std::string foo) : foo(foo) {}
std::function<void()> getDelegate() {
auto callback = [this]() {this->delegatedFn();};
return callback;
}
void delegatedFn() {
std::cout << foo << std::endl;
}
};
int main() {
Obj* obj = new Obj("bar");
std::function<void()> callback = obj->getDelegate();
callback();
delete obj;
//perform some type of check here whether function is valid, without needing to know whether the function is a delegate or not
if(callback) {
std::cout << "Callback is valid" << std::endl; //callback is still considered valid after obj is deleted
callback(); //no exception thrown, prints a random series of characters
}
else {
std::cout << "Callback is invalid" << std::endl;
}
return 0;
}

You can use smart pointers (std::shared_ptr/std::weak_ptr) instead of naked ones:
#include <iostream>
#include <string>
#include <functional>
#include <memory>
class Obj {
public:
std::string foo;
Obj(std::string foo) : foo(foo) {}
void delegatedFn() {
std::cout << foo << std::endl;
}
};
int main() {
auto obj = std::make_shared<Obj>("bar");
std::weak_ptr<Obj> ptr = obj;
std::function<void()> callback = [ptr](){
auto sh = ptr.lock();
if(sh) { std::cout << "valid" << std::endl; sh->delegatedFn(); }
else { std::cout << "invalid" << std::endl; }
};
callback();
obj = nullptr;
callback();
return 0;
}
In this case you are not directly checking the validity of a std::function (that is valid when you assign it something, even if that something captures a dangling pointer).
Instead, you check that the referred object is still alive from within the function itself.

The broadcaster/listener pattern I use looks like this:
template<class...Args>
struct broadcaster {
std::vector< std::weak_ptr< std::function<void(Args...)> > > callbacks;
void operator()(Args...args) const {
std::remove_erase_if( begin(callbacks), end(callbacks), [](auto&& ptr){return !ptr;} );
auto tmp = callbacks;
for (auto pf : tmp) {
if (pf && *pf) (*pf)(args...);
}
}
std::shared_ptr<void> listen( std::shared_ptr<std::function<void(Args...)>> f ) {
callbacks.push_back(f);
return f;
}
std::shared_ptr<void> listen( std::function<void(Args...)> f ) {
auto ptr = std::make_shared<std::function<void(Args...)>>(std::move(f));
return listen(ptr);
}
};
Listeners to a message .listen their callback with broadcaster. They get back a shared_ptr<void> token.
So long as that token exists, the broadcaster will send messages at the function object passed in.
Obj would either store a std::vector<std::shared_ptr<void>> tokens or a single std::shared_ptr<void>. When it was destroyed, its listeners would automatically deregister.
Alternatively, Obj could inherit from shared_from_this. Then it implements
std::function<void()> delegate;
std::shared_ptr<std::function<void()>> getDelegatedFn() {
if (!delegate) delegate = [this]{ this->delegateFn(); }
return {
&delegate,
shared_from_this()
};
}
which shares the lifetime of the Obj instance itself (uses the aliasing constructor of shared_ptr). Pass this to listen and done.

Related

Attach callback function without `std::function` [duplicate]

I want to be able to call functions based on the data I read from file.
So for each item type, I want to call the desired reader method.
I wrote this code, but it does not compile where I want to add function pointers to the map. What is wrong?
#include <vector>
#include <map>
#include <iostream>
class reader
{
std::map< std::string, void(*)()> functionCallMap; // function pointer
void readA(){ std::cout << "reading A\n";};
void readB(){ std::cout << "reading B\n";};;
public:
reader()
{
*functionCallMap["A"] = &reader::readA;*
*functionCallMap["B"] = &reader::readB;*
}
void read()
{
auto (*f) = functionCallMap["A"];
(*f)();
}
};
I am filling the map at Constructor.
You can use std::function with a lambda or std::bind :
class reader
{
std::map<std::string, std::function<void()>> functionCallMap;
void readA() { std::cout << "reading A\n"; };
void readB() { std::cout << "reading B\n"; };
public:
reader()
{
functionCallMap["A"] = [this]() { readA(); };
functionCallMap["B"] = std::bind(&reader::readB, this);
}
void read()
{
functionCallMap["A"]();
functionCallMap["B"]();
}
};
You need to use pointers to member functions, like this:
class reader
{
using FuncPtr = void(reader::*)(); // function pointer
std::map< std::string, FuncPtr> functionCallMap;
void readA(){ std::cout << "reading A\n"; }
void readB(){ std::cout << "reading B\n"; }
public:
reader()
{
functionCallMap["A"] = &reader::readA;
functionCallMap["B"] = &reader::readB;
}
void read()
{
auto f = functionCallMap["A"];
(this->*f)();
}
};
int main()
{
reader r;
r.read();
}
There are two answers so far, this and this.
The obvious difference is that one uses std::function and other uses function pointers. This is not the important difference!!
The key point is that the member functions are non-static member functions. So, they are not of type void().
They are of type void(reader::*)(). Thus, they can be only called if an object of type is reader is given; one can understand this somewhat as a hidden parameter.
The first answer just fixes the problem by specifying the correct type. This can be done using function pointers (as presented) or using std::function (The latter is much more expensive!).
The second answer fixes the problem by binding the function pointer to the particular instance of the class. After binding, the type is then indeed void(). This cannot be done using raw function pointers (because they can only point to a function and not an object/function pair!).
I ended up with this solution. It does the job, but I have some doubts over its aesthetics. Anyway, to sum up, I ended up with this code:
#include <map>
#include <iostream>
#include <functional>
class reader
{
std::map< std::string, std::function<void(std::string tableName)>> functionCallMap; // function pointer
void readA(const std::string tableName){ std::cout << "reading:" << tableName<< "\n"; }
void readB(const std::string tableName){ std::cout << "reading:" << tableName <<"\n"; }
public:
reader()
{
functionCallMap["A"] = std::bind(&reader::readA, this, std::placeholders::_1);
functionCallMap["B"] = std::bind(&reader::readA, this, std::placeholders::_1);
}
void read()
{
const std::string table_name = "A";
functionCallMap[table_name](table_name);
}
};
int main()
{
reader r;
r.read();
}
I pass the table name to the reader, it is nicely done with the bind and placeholder.

How to safely use callbacks when the bound function could be deleted

In the following code, we are creating an object, bind one function and call it before then after deleting the object.
This obviously leads to a segmentation fault as the underlying object was used after deletion.
In the context of a library providing callbacks for asynchronous data, how are we supposed to prevent callback functions to point to a nullptr?
You can test at cpp.sh/5ubbg
#include <memory>
#include <functional>
#include <iostream>
class CallbackContainer {
public:
std::string data_;
CallbackContainer(std::string data): data_(data) {}
~CallbackContainer() {}
void rawTest(const std::string& some_data);
};
void CallbackContainer::rawTest(const std::string& some_data) {
std::cout << data_ << " " << some_data << std::endl;
}
int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));
auto callback = std::bind(&CallbackContainer::rawTest, container.get(), std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
Returns:
> Internal data Before
> 0x7178a3bf6570
> 0x7178a3bf6570
> Error launching program (Segmentation fault)
If you can share ownership, do this:
int main(int /* argc */, char const** /* argv */) {
std::shared_ptr<CallbackContainer> container; // shared pointer
container.reset(new CallbackContainer("Internal data"));
// shared with functor
auto callback = std::bind(&CallbackContainer::rawTest, container, std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
If not, you should somehow pass invalidity to function object explicitly.
This assumes that you know when container is deleted, and manually invalidate explicitly before that:
int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));
std::atomic<CallbackContainer*> container_raw(container.get());
auto callback = [&container_raw] (std::string data)
{
if (auto c = container_raw.load())
c->rawTest(data);
};
callback("Before");
std::cout << &callback << std::endl;
container_raw.store(nullptr);
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}
For asio cases, usually shared_from_this() is used, like std::bind(&MyClass::MyMemFunc, shared_from_this(), ptr);
The way I prefer while working with boost asio:
I faced the same issue while working with boost asio. We need to register callbacks to io_service and it was difficult to implement some sort of Manager class which manages lifetime of the objects we may create.
So, I implement something that was suggested by Michael Caisse in cppcon2016. I started passing the shared_ptr to the object to the std::bind.
I used to extend the lifetime of the object and in the callback, you can decide to either extend the lifetime of the object again (by registering the callback again) or let it die automatically.
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
auto func = std::bind(&MyClass::MyMemFunc, this, ptr);
ptr.reset();
In the context of a library providing callbacks for asynchronous data, how are we supposed to prevent callback functions to point to a nullptr?
I wouldn't say that's the best solution but using by my above approach, you can detect if you need to proceed further in your callback or not.
It might not be the efficient way but it won't cause any undefined behavior.
void CallbackContainer::rawTest(const std::string& some_data, std::shared<CallbackContainer> ptr)
{
if (ptr.use_count() == 1) {
// We are the only owner of the object.
return; // and the object dies after this
}
std::cout << data_ << " " << some_data << std::endl;
}
EDIT:
An example code that shows how to do it using std::enable_shared_from_this:
#include <iostream>
#include <memory>
#include <functional>
class ABCD: public std::enable_shared_from_this<ABCD> {
public:
void call_me_anytime()
{
std::cout << "Thanks for Calling Me" << std::endl;
}
public:
ABCD(void)
{
std::cout << "CONSTRUCTOR" << std::endl;
}
~ABCD(void)
{
std::cout << "DESTRUCTOR" << std::endl;
}
};
int main(void)
{
auto ptr = std::make_shared<ABCD>();
auto cb = std::bind(&ABCD::call_me_anytime, ptr->shared_from_this());
ptr.reset();
std::cout << "RESETING SHARED_PTR" << std::endl;
std::cout << "CALLING CALLBACK" << std::endl;
cb();
std::cout << "RETURNING" << std::endl;
return 0;
}
Output:
CONSTRUCTOR
RESETING SHARED_PTR
CALLING CALLBACK
Thanks for Calling Me
RETURNING
DESTRUCTOR
As a followup, we decided to use roscpp method which is similar to Alex Guteniev's proposition.
Instead of doing std::bind explicitly, we use it internally and keep the parent as std::weak_ptr<const void> pointer to the std::shared_ptr<P> (as it would conflict with unique_ptr).
The API looks like:
std::shared_ptr<Container> container;
queue.subscribe(&Container::callback_method, container);
The subscription function is as following with T the explicit type of the data (Class-wise) but P the implicit class of the Parent class (Container in this case).
template <class P>
std::shared_ptr<ThreadedQueue<T>> subscribe(void (P::*function_pointer)(std::shared_ptr<const T>), std::shared_ptr<P> parent, size_t queue_size = -1) {
callback_ = std::bind(function_pointer, parent.get(), std::placeholders::_1);
parent_ = std::weak_ptr<const void>(parent);
}
When calling the callback, we do the following check:
if(auto lock = parent_.lock()) {
callback_(data);
}

enable_shared_from_this Vs Direct Assignment

Why should I use enable_shared_from_this as I can get the same effect via plain assignment also.
struct A : std::enable_shared_from_this<A> {
std::shared_ptr<A> getptr() {
return shared_from_this();
}
};
int main () {
// What is the differentce between this code
std::shared_ptr<A> p1 = make_shared<A>();
std::shared_ptr<A> p2 = p1->getptr();
// Vs this
std::shared_ptr<A> p1 = make_shared<A>();
std::shared_ptr<A> p2 = p1;
}
Because you can't get the "same" effect", at least not the one you may be thinking of.
There is no difference in the posted code methodologies, precisely because A inherits from std::enable_shared_from_this<A>. Both p1 and p2 are shared_ptr objects referring to the same concrete object (assuming only one of those sections is compiled for your tests, else you error on id name reuse).
std::enable_shared_from_this<T> allows you to acquire a std::shared_ptr<T> from some object, formally managed by some preexisting std::shared_ptr<T> of type T or derivative thereof, in locations where you have no std::shared_ptr<T> to the object to otherwise acquire, but need one for one reason or another. For example:
#include <iostream>
#include <memory>
struct A;
void foo(std::shared_ptr<A> arg)
{
}
struct A : std::enable_shared_from_this<A>
{
void method()
{
foo(shared_from_this());
}
};
int main ()
{
auto a = std::make_shared<A>();
a->method();
}
In the above example, foo requires a std::shared_ptr<A> as a parameter. From the body of A::method() no such mechanism exists without std::enable_shared_from_this<A> as a base. Without the std::enabled_shared_from_this<T> base, you would have to provide an alternative mechanism for passing the a shared pointer down the call chain until it reached foo. In short it would look something like this:
#include <iostream>
#include <memory>
struct A;
void foo(std::shared_ptr<A> arg)
{
}
struct A
{
void method(std::shared_ptr<A> me)
{
foo(me);
}
};
int main ()
{
std::shared_ptr<A> a = std::make_shared<A>();
a->method(a);
}
which is obviously dreadful and hideous. Further, there is no guarantee me in method is actually a std::shared_ptr<T> of this. Thus the standards committee blessed us with std::enable_shared_from_this<T>.
It's probably worth mentioning what shared_from_this is 'for'.
The most common use case is to 'keep myself alive' while some asynchronous process is running. A good example of this would be a completion handler, another would be a callback on 'this' when this is controlled by a shared_ptr.
for example:
#include <memory>
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
using namespace std::literals;
template<class Handler>
void long_process_with_completion_handler(Handler done)
{
std::thread([done] {
std::cout << "long process starts" << std::endl;
std::this_thread::sleep_for(2000ms);
done();
}).detach();
}
struct controller : std::enable_shared_from_this<controller>
{
auto get_lock() const {
return std::unique_lock<std::mutex>(_mutex);
}
void start() {
long_process_with_completion_handler([self = shared_from_this()] {
auto lock = self->get_lock();
std::cout << "all complete" << std::endl;
});
}
mutable std::mutex _mutex;
};
int main()
{
std::condition_variable controller_done;
std::mutex done_mutex;
bool is_controller_done = 0;
// make shared controller
// start its processing
auto pcontroller = std::shared_ptr<controller>{ new controller,
[&](auto*p) {
delete p;
auto lock = std::unique_lock<std::mutex>(done_mutex);
is_controller_done = true;
std::cout << "controller destroyed" << std::endl;
lock.unlock();
controller_done.notify_all();
}};
pcontroller->start();
// destroy the controlling pointer. but our controller is still running...
pcontroller.reset();
auto lock = std::unique_lock<std::mutex>(done_mutex);
controller_done.wait(lock, [&]{ return is_controller_done;});
std::cout << "program ends" << std::endl;
}
The shared-from-this functionality enables you to obtain a shared_ptr to a shared_ptr-managed object when all you have is a raw pointer or a reference.
Just creating a shared_ptr directly from the raw pointer would create a new, unrelated reference counter.
The use case of enable_shared_from_this and shared_from_this is clear, and yet I tend to say that in most use cases it can be dropped in favor of a static method that gets a shared_ptr and then creates a new shared_ptr from it (in a very similar manner to the approach suggested by the OP, but with a static method to support the creation of the new shared_ptr).
The advantage of the static method approach is that you won't fall in the bug of trying to get shared_from_this when there is no underlying shared_ptr for this instance, resulting with bad_weak_ptr.
The disadvantage is that the API is implicitly asking the caller to come with a shared_ptr, so if the caller has just a raw pointer to an instance he can't use it (the caller may create a shared_ptr from the raw pointer and call the method, but how can he tell if the original raw pointer was not managed already by a shared_ptr?). On the other hand, if the user has in hand a unique_ptr he should be positively sure that turning it to shared_ptr in order to call the static method should be fine.
In a way the advantage and disadvantage are two sides of the same coin.
I would prefer in most cases to require the API to work with shared_ptr (it already depends on that in a way) rather than allowing working with any kind of a pointer, with the hope that there is a managed shared_ptr for it. This goes well with the advice of having APIs that cannot be easily used in a wrong way.
Here is the code presented by #RichardHodges (great example!) using the static method approach instead of using enable_shared_from_this:
// code based on Richard Hodges example
template<class Handler>
void long_process_with_completion_handler(Handler done) {
std::thread([done] {
std::cout << "long process starts" << std::endl;
std::this_thread::sleep_for(2000ms);
done();
}).detach();
}
// without the need to inherit from std::enable_shared_from_this
struct Controller {
auto get_lock() const {
return std::unique_lock<std::mutex>(_mutex);
}
static void start(std::shared_ptr<Controller>& pcontroller) {
long_process_with_completion_handler(
[self = std::shared_ptr<Controller>(pcontroller)] {
auto lock = self->get_lock();
std::cout << "all complete" << std::endl;
});
}
mutable std::mutex _mutex;
};
int main() {
std::condition_variable controller_done;
std::mutex done_mutex;
bool is_controller_done = 0;
// make shared controller and start its processing
auto pcontroller = std::shared_ptr<Controller>{ new Controller,
[&](auto*p) {
delete p;
auto lock = std::unique_lock<std::mutex>(done_mutex);
is_controller_done = true;
std::cout << "controller destroyed" << std::endl;
lock.unlock();
controller_done.notify_all();
}};
Controller::start(pcontroller);
// destroy the controlling pointer. but our controller is still running...
pcontroller.reset();
auto lock = std::unique_lock<std::mutex>(done_mutex);
controller_done.wait(lock, [&]{ return is_controller_done;});
std::cout << "program ends" << std::endl;
}
Code: http://coliru.stacked-crooked.com/a/281b0ef6d1b31c56

unique_ptr and default constructible pointer

Recently I tried to reinvent scope guard via std::unique_ptr (NOTE: Deleter has the member typedef pointer — is a specially handled case of std::unique_ptr):
#include <type_traits>
#include <utility>
#include <memory>
#include <iostream>
#include <cstdlib>
#include <cassert>
namespace
{
template< typename lambda >
auto
make_scope_guard(lambda && _lambda)
{
struct lambda_caller
{
using pointer = std::decay_t< lambda >;
void
operator () (lambda & l) const noexcept
{
std::forward< lambda >(l)();
}
};
return std::unique_ptr< std::decay_t< lambda >, lambda_caller >(std::forward< lambda >(_lambda));
}
}
int
main()
{
std::cout << 1 << std::endl;
{
std::cout << 2 << std::endl;
[[gnu::unused]] auto && guard_ = make_scope_guard([&] { std::cout << __PRETTY_FUNCTION__ << std::endl; });
std::cout << 3 << std::endl;
}
std::cout << 5 << std::endl;
return EXIT_SUCCESS;
}
Such an approach works fine for simple pointer to free function void f() { std::cout << 4 << std::endl; } passed to make_scope_guard, but not for any lambda passed to make_scope_guard.
This is due to an abundance of ... = pointer() into the std::unique_ptr definition (function default parameter, defaulting data memebers etc), but I can't find the DefaultConstructible requirement for pointer into this article.
Is it mandatory, that the pointer should match the std::is_default_constructible requirement?
It tested against libc++ and against libstdc++ using not too old clang++ -std=gnu++1z.
Seems, there should be language extension for lambdas: if auto l = [/* possible capture list */] (Args...) { /* code */; }; then using L = decltype(l); is equivalent to struct L { constexpr void operator () (Args...) const noexcept { ; } }; for some Args..., isn't it?
ADDITIONAL:
Providing the instance D{} of following DefaultConstructible class to make_scope_guard(D{}) requires commented out code to be uncommented in the context if (p) { ..., where p is of type D:
struct D { void operator () () const noexcept { std::cout << __PRETTY_FUNCTION__ << std::endl; } /* constexpr operator bool () const { return true; } */ };
A unique_ptr is still a pointer. You cannot shoehorn a lambda into it. From [unique.ptr]:
A unique pointer is an object that owns another object and manages that other object through a pointer.
More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose of
p when u is itself destroyed
[...]
Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
such a transfer, the following post-conditions hold: [...] u.p is equal to nullptr
A lambda is not a pointer. A lambda cannot equal nullptr.
That said, you're already making your own local struct, why not just use that to do the RAII scope guarding itself instead of deferring to unique_ptr? That seems like a hack at best, and takes more code to boot. You could instead just do:
template< typename lambda >
auto
make_scope_guard(lambda && _lambda)
{
struct lambda_caller
{
lambda _lambda;
~lambda_caller()
{
_lambda();
}
};
return lambda_caller{std::forward<lambda>(_lambda)};
}
If you need to support release, you can wrap _lambda inside of boost::optional so that lambda_caller becomes:
struct lambda_caller
{
boost::optional<lambda> _lambda;
~lambda_caller()
{
if (_lambda) {
(*_lambda)();
_lambda = boost::none;
}
}
void release() {
_lambda = boost::none;
}
};

C++11 styled callbacks?

I have a void function inside of a class. In old C++ i'd make a function static taking the class name as a parameter and had my own class which took a static void function + a void* for me to easily call it.
However that feels old school. It also isn't templated which feels like i could be doing more. What is a more modern way of creating callbacks to myclassVar.voidReturnVoidParamFunc
Use std::function and lambdas (or std::bind()) to store callables:
#include <functional>
#include <iostream>
class Test
{
public:
void blah() { std::cout << "BLAH!" << std::endl; }
};
class Bim
{
public:
void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }
int main()
{
// store the member function of an object:
Test test;
std::function< void() > callback = std::bind( &Test::blah, test );
callback();
// store a callable object (by copy)
callback = Bim{};
callback();
// store the address of a static function
callback = &boum;
callback();
// store a copy of a lambda (that is a callable object)
callback = [&]{ test.blah(); }; // often clearer -and not more expensive- than std::bind()
callback();
}
Result:
BLAH!
BIM!
BOUM!
BLAH!
Compiles and run: http://ideone.com/T6wVp
std::function can be used as any copyiable object, so feel free to store it somewhere as a callback, like in object's member. It also means that you can freely put it in standard containers, like std::vector< std::function< void () > > .
Also note that equivalent boost::function and boost::bind have been available for years.
For an example of passing in parameters to a C++ 11 callback using Lambda's and a vector, see http://ideone.com/tcBCeO or below:
class Test
{
public:
Test (int testType) : m_testType(testType) {};
void blah() { std::cout << "BLAH! " << m_testType << std::endl; }
void blahWithParmeter(std::string p) { std::cout << "BLAH1! Parameter=" << p << std::endl; }
void blahWithParmeter2(std::string p) { std::cout << "BLAH2! Parameter=" << p << std::endl; }
private:
int m_testType;
};
class Bim
{
public:
void operator()(){ std::cout << "BIM!" << std::endl; }
};
void boum() { std::cout << "BOUM!" << std::endl; }
int main()
{
// store the member function of an object:
Test test(7);
//std::function< void() > callback = std::bind( &Test::blah, test );
std::function< void() > callback = std::bind( &Test::blah, test );
callback();
// store a callable object (by copy)
callback = Bim{};
callback();
// store the address of a static function
callback = &boum;
callback();
// store a copy of a lambda (that is a callable object)
callback = [&]{ test.blah(); }; // might be clearer than calling std::bind()
callback();
// example of callback with parameter using a vector
typedef std::function<void(std::string&)> TstringCallback;
std::vector <TstringCallback> callbackListStringParms;
callbackListStringParms.push_back( [&] (const std::string& tag) { test.blahWithParmeter(tag); });
callbackListStringParms.push_back( [&] (const std::string& tag) { test.blahWithParmeter2(tag); });
std::string parm1 = "parm1";
std::string parm2 = "parm2";
int i = 0;
for (auto cb : callbackListStringParms )
{
++i;
if (i == 1)
cb(parm1);
else
cb(parm2);
}
}