C++ Generic command parser using variadic templates - c++

I'm trying to write some sort of command handler, which can tokenize an istringstream, automatically convert the tokens into variables of specific types and call a callback function with the converted variables as arguments. Here is simplified version of my code:
void Callback(int x, char y, float z) {
// do whatever
// note: For simplicity, I use a callback with a fixed signature
// here. In my actual implementation, the callback can be
// called with any number and types of arguments - but that
// I have solved already.
}
template<typename T>
T GetNextArgument(std::istringstream& strm) {
// get one token from the input stream and convert it to the required type
T val;
strm >> val;
return val;
}
template<typename ...Args>
void ParseAndExecute(std::istringstream& input_stream) {
Callback(GetNextArgument<Args>(input_stream)...);
}
int main() {
std::istringstream strm("15 a 17.3");
ParseAndExecute(strm);
return 0;
}
The problem I have is that the ParseAndExecute() function after parameter pack expansion looks like this:
void ParseAndExecute(std::istringstream& strm) {
Callback(GetNextArgument<int>(strm),
GetNextArgument<char>(strm),
GetNextArgument<float>(strm));
}
Since the order of evaluation of the arguments is not defined, the tokens may be taken from the stream in incorrect order (and in my case, they always are). Instead I would need the expansion to give me something more like that:
void ParseAndExecute(std::istringstream& strm) {
int a1 = GetNextArgument<int>(strm);
char a2 = GetNextArgument<char>(strm);
float a3 = GetNextArgument<float>(strm);
Callback(a1, a2, a3);
}
But I cannot see how to achieve that with parameter pack expansion. Maybe with a recursive template...? Or do you have any other suggestion to achieve a similar functionality?

struct Caller {
template<class...Args>
Caller(Args&&... args) { Callback(std::forward<Args>(args)...); }
};
template<typename ...Args>
void ParseAndExecute(std::istringstream& input_stream) {
Caller{GetNextArgument<Args>(input_stream)...};
}

You could use an intermediate std::tuple with list initialization because left-to-right order is mandatory in this case:
std::tuple<Args...> tuple_args = {GetNextArgument<Args>(input_stream)... };
std::apply([](auto&&... args) {
Callback(std::forward<decltype(args)>(args)... );
}, std::move(tuple_args));
You have to use a lambda if Callback does not have a fixed signature as you mentioned and you want to rely on deduction.

Related

Generate argument names from list of types to forward to another function

I would like to generate a function that forwards its arguments to another function. I know that std::function does it somehow, but I cannot seem to find the right syntax myself.
It would be ok for my usecase to use som kind of template magic, but i want
the user to be able to get information on the calling types when they use the function, like std::function does.
My usecase uses class member functions, so a solution that only works in that context is accepted. I tried to created the smallest example code possible.
#include <iostream>
// Macro usage cannot be changed
#define ARGS int, int
void otherFunction(int x, int y) {
std::cout << x << "," << y << "\n";
}
// This is the behaviour i want
void expectedImplementation(int _1, int _2) {
otherFunction(_1, _2);
}
// This works, but it prevents the user to view the expected
// types in their IDE
template <typename ...Args>
void templateVersion(Args ... args) {
otherFunction(args...);
}
// This is the version I cannot get to work
// It does not need to look like this, but it needs to get
// its argument types from
//void func(ARGS) {
// otherFunction(/*how?*/);
//}
int main() {
expectedImplementation(1, 2);
templateVersion(1, 2);
//func(1, 2);
}
godbolt
How do I accomplish this?
Edit:
The function that needs to be forwarded to is also different for each instance of the function.
Edit 2:
Ok, It seems like it's hard to specify the context without the context. Here is the actual code that I want to generalize. Here Is the template magick stuff where it should fit in. No memory should be used, otherwise I would just use the solution I have now with template parameter packs.
Edit 3:
A better example:
#include <iostream>
#define ARGS int, int
struct Inner {
void otherFunction(int x, int y) {
std::cout << x << y << std::endl;
}
};
struct Wrapper {
Inner inner;
// This works, but it prevents the user to view the expected
// types in their ide
template <typename ...Args>
void templateVersion(Args ... args) {
inner.otherFunction(args...);
}
// The concept I try to figure out
void function(ARGS) { // It does not need to look exactly like this
// , but functionally it needs to be somithing like it
// Forward the arguments to the `ìnner` class
}
};
int main() {
auto wrapper = Wrapper{};
wrapper.templateVersion(10, 20);
}
Your macro ARGS does not define named arguments. You cannot forward the type of unnamed arguments. That's a limitation of the language.
Either forget about using macros, and change your function definiton:
void func(int a, int b) {
otherFunction(a, b);
}
Or change the definition of the macro:
#define ARGS int a, int b
void func(ARGS) {
otherFunction(a, b);
}
That said, nothing beats the template solution. Make sure you use perfect forwarding.
template <typename ...Args>
void templateVersion(Args&& ... args) {
otherFunction(std::forward<Args>(args)...);
}

How to properly pass C strings to a lambda inside a variadic template function

Here is my complex situation:
I have a function using variadic template and lambda:
template<typename...Args>
void foo(Args...args) {
// the arguments are passed to the lambda
_func = [args...](){ do_sth(args...); };
}
On observing specific events, the lambda _func would be fired.
My problem is, some of the arguments I passed are C strings, they could be pointing to temporary std string like this:
const char *pStr = __temp_std__string__.c_str();
Given I call foo(pStr);, and when _func is called, the temporary string that pStr is pointing to, has been released. I would like to know whether there exists a generic way to handle this. I am using C++11.
EDIT:
Perhaps I should post my whole story, as many of you advise to pass std::string instead of C strings, there are reasons that I can't escape from it.
I am developing games using cocos2d-x, which deploys C++11. What I want to do is to support auto-localisation of labels when players change their preferences of languages (selected from a UI).
I have saved the text in a couple of files, and each of them contains the localised text of a single language, they are basically under the following structure:
{
"key1" : "_localized_text1_",
"key2" : "_localized_text2_",
...
}
The idea is to observe the event on change of language's preference (through a notification), and I would get a key indicating that language from it, so as to fetch the localised text from the proper file. Here is the way how I implement it in the object class Label:
class Label {
// this method would update the label's displayed text
void setString(const std::string& text);
// set a callback for changing language
void setOnLanguageChangeFunc(std::function<void(Notification*)> func);
// set a localised text, which would be updated on changing language
void setLocalizeString(const std::string& key);
};
the core function is setLocalizeString (I skip the implementations of the other 2 methods as they are intuitive enough from their declaration):
void Label::setLocalizeString(const std::string& key) {
// the callback lambda
auto callback = [=](Notification *pNotification){
setString(LOCALIZED_STRING(key));
}
// assign the lambda
setOnLanguageChangeFunc(callback);
}
where LOCALIZED_STRING is the macro helper of fetching localised string with a key; and the lambda callback would be saved as local member variable of Label in setOnLanguageChangeFunc.
This works great in most cases, what makes the situation complicated is, there are format specifiers involved in the localised text, for example:
{
...
"keyN" : "%s eats %d cookies",
...
}
Such format placeholders are passed dynamically in codes:
// formatStr = "Tom eats 5 cookies"
std::string formatStr = StringKit::stringWithFormat("%s eats %d cookies", "Tom", 5);
where StringKit is a utility to format the string, and it accepts variadic arguments which would be passed to vsnprintf to yield the output. Now you know why I need to pass C string and not std::string, its just due to the underlying method to format string.
Now I have to modify Label::setLocalizeString so that it could digest the possible variadic arguments:
template<typename... Args>
void setLocalizeString(const std::string& key, Args... args)
{
// the callback lambda
auto callback = [=](Notification *pNotification){
setString(StringKit::stringWithFormat(LOCALIZED_STRING(sKey), args...));
}
// assign the lambda
setOnLanguageChangeFunc(callback);
}
And this is its use case:
// on changing language, the label would display "Tom eats 5 cookies"
pLabel->setLocalizeString("keyN", "Tom", 5);
This case would work like a charm as that C string argument is global, but when it is passed from a temporary std::string:
std::string tempStr = "Tom";
pLabel->setLocalizeString("keyN", tempStr.c_str(), 5);
The C string "Tom" would lose the value on calling the lambda callback, since the pointed std::string, has been gone.
I have tried several ways, like playing with tuple things, or capturing a wrapper class of basic types in the lambda, but none of them could solve the problem. However, I think there should exist some tricky solutions.
This problem is not related to lambdas or variadic functions - it also occurs if you simply store the string:
const char* global_storage;
int main()
{
{
std::string s = "hi";
global_storage = s.c_str();
}
// !!! `global_storage` points to deleted memory!
use(global_storage);
}
You need to make sure the string lives long enough. Using std::string instead of const char* is a great starting point:
std::string global_storage;
int main()
{
{
std::string s = "hi";
global_storage = std::move(s);
}
// OK, local string was moved into `global_storage`.
use(global_storage.c_str());
}
If you really need to use a C-style string, just store it in the lambda/whatever as a std::string, then call .c_str() when you need to use it, not when storing it.
You need to convert your char const* arguments to std::string when storing it in lambda. This is one possible way, i can propose:
#include <iostream>
#include <tuple>
using namespace std;
template<typename T, typename R = conditional_t<is_same<T, char const*>::value, string, T>>
R bar (T &&value) {return value;}
template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple_impl(std::basic_ostream<Ch,Tr>& os,
const Tuple & t,
std::index_sequence<Is...>)
{
using swallow = int[]; // guaranties left to right order
(void)swallow{0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...};
}
template<class Ch, class Tr, class... Args>
decltype(auto) operator<<(std::basic_ostream<Ch, Tr>& os,
const std::tuple<Args...>& t)
{
os << "(";
print_tuple_impl(os, t, std::index_sequence_for<Args...>{});
return os << ")";
}
template<typename...Args>
decltype(auto) foo(Args...args)
{
return [args = make_tuple(bar(args)...)] () { cout<< args; return; };
}
int main() {
string *s = new string("Hello, World!");
const char *p = s->c_str();
auto f = foo(1, p, 3.14);
delete s;
f();
return 0;
}
Function foo returns lambda that stores variadic arguments as tuple, where each char const* element is converted to std::string automatically. After that you can free temporary string. It's now should be safe to call that lambda after freeing.
IdeOne.com

C++ member function pointer with different arguments - or is this bad anyway?

Even though I fear that you will tell me that this topic was covered several time, I dare to ask it, since I was not able to generate a solution. Probably I was just looking for the wrong thing...
Assume that I have a function which receives a "mode" from some external function. Depending on the mode, the function will call different member functions of the same object. This works well for me with member function without any argument, but I did not find out how to extend it to members with arguments. In the real world application, the arguments are not int/float but a more complex classes and the call is nested inside different loops, so I would need to put switch statements several times which I consider ugly.
Question A: Is it possible to easily add support for member functions with arguments based on the existing design? If yes, how does one do that? If possible without external libraries...
Question B: Is this a completely wrong/bad approach? How would I do it better?
Thanks a lot for your help and explanations.
Chris
header excerpt:
typedef void (Object::*memberFunction)();
class Object
{
void memberFnNoArg();
void memberFnWithIntArg(int arg);
void memberFnWithFloatArg(float arg);
}
cpp excerpt:
void function()
{
int mode = getModeFromSomewhere();
int intArg = 33;
float floatArg = 66.6;
switch(mode)
{
case 1:
process(&Object::memberFnNoArg);
break;
case 2:
process(&Object::memberFnWithIntArg, ???); // how can I pass arg?
break;
case 3:
process(&Object::memberFnWithFlaotArg, ???); // how can I pass arg?
break;
default:
// do nothing;
}
}
void process(Object::memberFunction func)
{
Object object;
// loops, called several times, ...
(object.*func)(); // how do I handle different arguments?
}
Wrapping the algorithm in a functor is the right approach, and std::function is a nice functor provided by the Standard library.
But using boost::bind or even std::bind, as suggested by Tomek, is really ugly IMO, and rapidly gets out of control when binding multiple arguments.
If you have a recent compiler you can use a lambda instead, which makes Tomek's example look like:
std::function<void(Object*)> f =
[](Object* const that){ that->memberFnNoArg(); };
int int_value = 22;
std::function<void(Object*)> f2 =
[int_value](Object* const that){ that->memberFnIntArg(int_value); };
Object o;
f(&o);
f2(&o);
There are a few characters to set up the lambda, but the member access syntax is extremely natural and it's obvious how you make changes.
Of course, you can make the parameter a reference to the object if you really want, but I prefer pointers here.
Have a look at std::function and std::bind, they seem to fit perfectly what you need.
EDIT:
std::function<void(Object &)> f = &Object::memberFnNoArg;
std::function<void(Object &)> f2 = std::bind(&Object::memberFnWithIntArg, _1, 22);
Object o;
f(o);
f2(o);
should work out of a box as far as I remember.
Is this what you need?
You could use a varadic template function:
template <typename... Args>
void process(void (Object::*func)(Args...),Args... args)
{
Object object;
// loops, called several times, ...
(object.*func)(args...);
}
Here is a full example:
#include <iostream>
struct Object
{
void memberFnNoArg()
{
std::cout << "Object::memberFnNoArg()\n";
}
void memberFnWithIntArg(int arg)
{
std::cout << "Object::memberFnWithIntArg(" << arg << ")\n";
}
void memberFnWithFloatArg(float arg)
{
std::cout << "Object::memberFnWithFloatArg(" << arg << ")\n";
}
};
template <typename... Args>
void process(void (Object::*func)(Args...),Args... args)
{
Object object;
// loops, called several times, ...
(object.*func)(args...);
}
int main()
{
process(&Object::memberFnNoArg);
process(&Object::memberFnWithIntArg,5);
process(&Object::memberFnWithFloatArg,2.7F);
return 0;
}
One way I see around this would be to use a variable arguments (pretty much like printf, sprintf does it). (Or maybe with stdc libraries, passing a list of different types.)
The reason is, that the argument list is part of the function pointer type, so you'd essentially need a process function with variable arguments and then the memberFunction probably needs to be one of that type too.
Below is a plain (non member) sample of how to pick up variable arguments (member functions would essentially work the same). See stdarg.h.
typedef void (*var_function)(int typearg, ...);
void print_arg(int typearg, ...)
{
va_list ap;
int i;
va_start(ap, typearg);
if (typearg==1) { // int
int i= va_arg(ap, int);
printf("%d ", i);
}
else
if (typearg==2) { // float
float f= va_arg(ap, float);
printf("%f ", f);
}
else
if (typearg==3) { // char *
char *s= va_arg(ap, char *);
printf("%s ", s);
}
....
va_end(ap);
}
// calling function with different types
int main()
{
print_arg(1, 999);
print_arg(2, 3.1415926);
print_arg(3, "Hello");
....
process(print_arg, 3, "via pointer);
Sounds like packaged_task. Also check out Tomek's suggestion.
Though IRL I'd go ahead asking lots of questions on why you need it in the first place. Possibly your work could be better covered using std::future or other higher level facility,
Can't each function (memberFn**) be a member of argument classes ?
class BaseArg
{
virtual void Fn() = 0;
};
class IntArg : public BaseArg
{
void Fn();
};
class FloatArg : public BaseArg
{
void Fn();
};
void function()
{
int mode = getModeFromSomewhere();
BaseArg* pArg;
if ( mode ... ){
pArg = new IntArg( 33 );
}
else {
pArg = new FloatArg( 66.6 );
}
pArg->Fn(); // Call the right function without a switch
// and without knowing the arguments
}
Same as other answers, but to show for member methods:
#include <iostream>
class Object
{
public:
void memberFnNoArg()
{
std::cout << "Object::memberFnNoArg()\n";
}
void memberFnWithIntArg(int arg)
{
std::cout << "Object::memberFnWithIntArg(" << arg << ")\n";
}
void memberFnWithFloatArg(float arg)
{
std::cout << "Object::memberFnWithFloatArg(" << arg << ")\n";
}
bool memberFnWithBoolReturn(int)
{
return true;
}
template <typename... Args>
void process(void (Object::*func)(Args...),Args... args);
// overload process
template <typename... Args>
bool process(bool (Object::*func)(Args...),Args... args);
};
template <typename... Args>
void process( void (Object::*func)(Args...),class Object* obj,Args... args)
{
(obj->*func)(args...);
}
template <typename... Args>
bool process( bool (Object::*func)(Args...),class Object* obj,Args... args)
{
return ((obj->*func)(args...)) ;
}
int main()
{
Object object;
process(&Object::memberFnNoArg,&object);
process(&Object::memberFnWithIntArg,&object,5);
process(&Object::memberFnWithFloatArg,&object,2.7F);
// overloaded process
printf("%d\n",process(&Object::memberFnWithBoolReturn,&object,1));
return 0;
}

variadic templates: invalid use of void expression

I'm trying to create a generic collection for events so that it'll be reusable for different kind of event-sets. While playing around with variadic templates, I came across THIS answer, which helped me for my example here:
#include <boost/test/unit_test.hpp>
#include <string>
#include <unordered_map>
namespace
{
struct Event3 {
static const int event_type = 3;
int a;
};
struct Event5 {
static const int event_type = 5;
double d;
};
struct Event7 {
static const int event_type = 7;
std::string s;
};
template <class ...K>
void gun(K...) {}
template <class... Ts>
class EventCollection
{
template <typename T>
void update_map(std::unordered_map<int, size_t> & map, const T &)
{
BOOST_CHECK(map.find(T::event_type) == map.end());
map[T::event_type] = sizeof(T);
}
public:
std::unordered_map<int, size_t> curr_map;
EventCollection(Ts... ts)
{
gun(update_map(curr_map, ts)...); // will expand for each input type
}
};
} // namespace
BOOST_AUTO_TEST_CASE( test_01 )
{
Event3 x{13};
Event5 y{17.0};
Event7 z{"23"};
EventCollection<Event3, Event5, Event7> hoshi(x, y, z);
BOOST_CHECK_EQUAL(hoshi.curr_map.size(), 3);
}
However, the line
gun(update_map(curr_map, ts)...); // will expand for each input type
gives me an 'error: invalid use of void expression'.
Can anybody tell me, how to solve this?
The problem is that your update_map returns void. Hence you cannot write this:
gun(update_map(curr_map, ts)...);
because the return values of update_map is supposed to be passed to gun as arguments.
The fix is to pass something to gun as argument, so you can do this:
gun( (update_map(curr_map, ts),0)...);
Now the expresssion (update_map(curr_map, ts),0) turns out to be 0 which is passed as argument to gun. That should work. You can think of this as:
T argmument = (update_map(curr_map, ts),0); //argument is 0, and T is int
--
Also, as the other answer pointed out that the order of evaluation of arguments to gun() are unspecified (means the order in which the function update_map is called, is unspecified) which may lead to undesired result. The other solution has given a solution to this problem. Here is another one (which is a bit tricky and easy!):
//ensure that the size of the below array is at least one.
int do_in_order[] = {0, (update_map(curr_map, ts),0)...};
Because the order of initialization of array elements are well-defined (from left-to-right), now all the calls to update_map happens in well-defined order.
update_map is a function that returns void.
That line consists of calling update_map, and then passing the return value to gun.
You cannot pass a void return value to another function.
Hence "invalid use of void expression".
There are many ways to fix this, including having update_map return struct empty {};
Note that your code results in the calls of update_map happening in an unspecified order. This can easily lead to unexpected behavior.
Might I suggest:
void do_in_order();
template<typename F0, typename... Functors>
void do_in_order( F0&& f0, Functors&& funcs... ) {
f0();
do_in_order( std::forward<Functors>(funcs)... );
}
then replace the call to gun with:
do_in_order([&]{update_map(curr_map, ts);}...); // will expand for each input type
which packages up the things to do into lambdas, which are then called in order that they are passed.
Now, this also does away with the need for an update_map function entirely:
do_in_order([&]{
BOOST_CHECK(curr_map.find(ts::event_type) == curr_map.end());
map[ts::event_type] = sizeof(ts);
}...);
which is awesome.

List of functions to be called. Have to have same signature. Better implementation?

My program reads in "commands" from a text file such as "w test.txt 5" for write to test.txt the number 5 or "r test.txt" for reading from test.txt. Instead of having a horrible switch loop to maintain I have a called aFunction which has function member
string name;
void (*thefunction)(char *argsIn[], char *out);
So I have a string name and a function pointer. Outside the class I have a
vector<aFunction> funcVec
which holds all the functions. When I read a command in from a text file the code looks through funcVec to find the correct function to call
So when funcVec.name = command read in
(*funcVec[i].theFunction(other values from the text file, output);
For example I may have the funciton read(char *argsIn[], char *out)
where argsIn would be an array containing test.txt, 5 and char out might be a 1 or 0 depending on whether the operation was successful.
However I don't really like this very much because all functions now have to have the signature (char *argsIn[], char *out) and it's up to the function to know what each parameter in the list means.
Can anyone think of a better implementation? Surely software that supports scripting has to cope with this sort of thing?
Note: you'd better use std::string and std::vector
The Command pattern is normally the way to do this, this allows "packing" the input/output arguments in the object and presenting a "blank" execution method void operator()() ensuring a common interface.
EDIT: a demonstration of Command (generic).
Define some commands:
struct Command: boost::noncopyable
{
virtual void do() = 0;
virtual void undo() = 0;
virtual ~Command() {}
};
class SaveFile: public Command
{
public:
explicit SaveFile(FileHandle f, Changes c): _file(file), _changes(c) {}
virtual void do() { _file.apply(_changes); }
virtual void undo() { _file.revert(_changes); }
private:
FileHandle _file;
Changes _changes;
};
class OpenFile: public Command
{
public:
explicit OpenFile(std::string filename): _filename(filename) {}
FileHandle get() const { return _file; }
virtual void do() { _file.load(_filename); }
virtual void undo() { /*nothing to be done*/ }
private:
std::string _filename;
FileHandle _file;
};
Example use of two stacks of actions: those to be performed, and those that have been performed.
typedef std::stack<std::unique_ptr<Command>> CommandStack;
void transaction(CommandStack& todo)
{
CommandStack undo;
try
{
while(!todo.empty())
{
todo.top()->do();
undo.push(std::move(todo.top()));
todo.pop();
}
}
catch(std::exception const&)
{
while(!undo.empty())
{
undo.top()->do();
undo.pop();
}
}
} // transaction
What you have to do reading these commands is threefold:
Find out which function to call.
Convert the list of argument strings into the arguments of the right type.
Call the function passing those arguments to do the whatever needs to be done.
To abstract #2 is pretty hard, as C++ has very little support for dealing with different types that are known only at runtime, but it's not impossible.
I have once seen an article where someone used template-meta programming to find out about the parameters of registered function, and then generate the code that breaks down string list into the matching arguments. Functions were kept in a map of key strings to function pointers (using type erasure to store functions with different signatures).
Here's a sketch about how to use type erasure to store different function pointer sin a map:
struct func_base {
virtual void operator()(std::istream&) const = 0;
};
template< typename F >
class function : public func_base {
public:
function(F f) : func_(f) {}
void operator()(std::string& arguments) const;
private:
func_base func_;
};
typedef std::map< std::string, std::shared_ptr<func_base> > func_map;
template< typename F >
void addFunc(func_map& map, const std::string& keyword, F f)
{
assert(map.find(keyword) == map.end());
map[keyword] = std::shared_ptr<func_base>(new function<T>(f));
}
That would leave function<F>::operator()() to chop the arguments into individual strings, convert them into the appropriate types, and then call the function with them.
Chopping the string into a list of arguments shouldn't be a problem, so I'll skip over that. The hard part is calling a function with the right parameters given that list. Note that the function's type is known within function<F>::operator()() at compile-time, so you have the whole of template-meta programming techniques at your disposal.
ISTR that article did this by creating tuples according to the function's parameter list and had the means to call any function given such a tuple. Here's you could create such tuples with recursive calls:
template< typename Tuple >
Tuple convert_args(const std::string& line)
{
Tuple result;
// I don't know tuples well enough yet, so here's just an
// algorithm rather than code:
// 1. read first argument from line and put it into tuple's first element
// 2. call yourself for a tuple that consists of the remaining elements of Tuple
// 3. fill the remaining tuple elements from the result of #2
return result
}
Then use traits to call those functions:
template<typename F>
struct func_traits;
template<typename R, typename A1>// function taking one arg
struct func_traits<R(*)()> {
typedef std::tuple<A1> arg_list;
static R call(R(*f)(), const arg_list& args)
{
return f(std::get<0>(arg_list)); // how do you access an element in a tuple
}
};
template<typename R, typename A1, typename A2>// function taking two args
struct func_traits<R(*)()> {
typedef std::tuple<A1,A2> arg_list;
static R call(R(*f)(), const arg_list& args)
{
return f(std::get<0>(arg_list), std::get<1>(arg_list));
}
};
// repeat for as many args as you'll need
A very simple implementation would be using std::map instead of std:vector which you've used:
typedef void (*FunctionType)(char *argsIn[], char *out);
std::map<std::string, FunctionType> functionMap;
//populate the functionMap
//key = commandName, value = function to be called;
functionMap["write"] = WriteFunc;
functionMap["read"]= ReadFunc;
//later use this map as
functionMap[commandName](arguments, output);