Is there a tidy way of associating metadata with functions in C++ - c++

I have a codebase with many command line options. Currently, each command line option lives in a table along with a function pointer to run if the command is passed in on the command line.
e.g.
static CommandFunction s_Commands[] =
{
{ "command1", Func1 },
{ "command2", Func2 },
{ "command3", Func3 },
etc...
};
My problem with this is, the table is huge, and the functions live elsewhere. I would prefer the string for the command to live right beside each function.
So for example:
COMMAND_ARG("command1")
void Func1()
{
dostuff
...
}
COMMAND_ARG("command2")
void Func2()
{
dostuff
...
}
COMMAND_ARG("command3")
void Func3()
{
dostuff
...
}
Is this possible?

You can do that with a template specialized by an address of a function:
#include <stdio.h>
// In a header file.
template<void(*Fn)()>
struct FnMeta
{
static char const* const meta;
};
// no definition of meta
// some.cc
void some() {}
template<> char const* const FnMeta<some>::meta = "some";
// another.cc
void another() {}
template<> char const* const FnMeta<another>::meta = "another";
// main.cc
int main() {
printf("%s\n", FnMeta<some>::meta);
printf("%s\n", FnMeta<another>::meta);
}
The idea above is that FnMeta<>::meta is not defined. However, different translation units (.cc files) can provide a definition of a specialization of FnMeta<>::meta. This way when FnMeta<X>::meta is used the linker finds the appropriate definition of it in another translation unit.

There are different approaches to this particular problem. You can use inheritance, by which you create a base Command and then implement some execute function (you can also implement help, validate....). Then create a dispatcher function that associates the names with the actual implementations of the commands (in a lookup table of sorts, possibly a map).
While this does not solve your issue with locality, that issue might or not be real. That is, the implementation of the commands might be all over the place, but there is a single place that determines what commands are available in the CLI.
If locality is such an important thing for you (at the cost of not having a single place in your source code where all commands in use are listed), you can provide a registration mechanism that is globally accessible, then provide a helper type that during construction will register the function into the mechanism. You can then create one such object with each function definition.
CommandRegistry& getCommandRegistry(); // Access the registry
struct CommandRegister {
CommandRegister(const char* name, Function f) {
getCommandRegistry().registerCmd(name,f);
}
// Optionally add deregistration
};
// ...
void Func2() {...}
static CommandRegister Func2Registration("function2",&Func2);
I personally prefer to go the other way... having a single place in the code where all commands are listed, as it allows for a single location in which to find the command (text) to code that executes it. That is, when you have a few commands and someone else needs to maintain one of them, it makes it easier to go from the command line to the actual code that executes it.

I agree with Maxim Yegorushkin's answer that it is best to try to use static mechanisms, but here's a couple of runtime approaches that meet the requirement of keeping the behavior and the function name together.
Approach #1, Command Object:
class AbstractCommand{
public:
virtual ~AbstractCommand() {}
virtual void exec() = 0;
virtual const char *commandName() const = 0;
};
class Command1 : public AbstractCommand{
public:
virtual void exec() { /* do stuff */ }
virtual const char *commandName() const { return "command name 1"; }
};
class Command2 : public AbstractCommand{
public:
virtual void exec() { /* do stuff */ }
virtual const char *commandName() const { return "command name 2"; }
};
static AbstractCommand *s_commands[] {
new Command1(),
new Command2(),
...,
0
};
Approach #2, function with selector:
enum CommandExecOption { GET_NAME, EXEC };
typedef void* (*command_func_t)( CommandExecOption opt );
void *Command1Func( CommandExecOption opt )
{
switch(opt){
case GET_NAME: return "command 1"; break;
case EXEC:
/* do stuff */
break;
}
return 0;
}
void *Command2Func( CommandExecOption opt )
{
switch(opt){
case GET_NAME: return "command 2"; break;
case EXEC:
/* do stuff */
break;
}
return 0;
}
command_func_t s_commands[] = {
Command1Func,
Command2Func,
...,
0
};

So you want to use preprocessor macros, huh? There are seams to be bad, but I use them frequently. This answer will be based on command registry:
class Command
{
public:
Command(std::string const& _name):name(_name){ registry[_name]=this; }
virtual ~Command() { registry.erase(name); }
static void execute( std::string const& name ) {
RegistryType::iterator i = registry.find(name);
if(i!=registry.end()) i->second->_execute();
//some exeption code here
}
protected:
virtual void _execute() = 0;
private:
const std::string name;
typedef std::map< std::string, Command* > RegistryType;
static RegistryType registry;
};
There are static registry that should be somewhere else than header:
Command::RegistryType Command::registry;
Lets look what we need (changed a bit to be simpler):
COMMAND_ARG( doSomething )
{
cout << "Something to do!" << std::endl;
}
So we need to create some object of a class that inherit from Command and have implemented _execute method. Since method can be defined outside of class this macro will enclose all needed code, and use the code in braced:
class CommanddoSomething : public Command {
public:
CommanddoSomething () : Command( "doSomething" ) {}
private:
virtual void _execute();
} commanddoSomething;
void CommanddoSomething :: _execute()
{
cout << "Something to do!" << std::endl;
}
So this is perfect place for a macro:
#define COMMAND_ARG( NAME ) \
class Command ## NAME : public Command { \
public: Command ## NAME () : Command( #NAME ) {} \
private: virtual void _execute(); \
} command ## NAME; \
void Command ## NAME :: _execute()
I hope you like it.

Related

Programmable access to the right virtual class child?

I have a virtual / parent class
and many children of this class.
I assume that these children are a different way of generating answers to questions - such as various communication protocols, with one API.
They can have different versions.
class A {
 public: virtual const char * [] GetProtocolName () {return "A"; }
 };
class B: public A {
public: virtual const char * [] GetProtocolName () {return "B"; }
};
class C: public B {
public: virtual const char * [] GetProtocolName () {return "C"; }
};
....
Let's assume that in the program I want to list my child class / children list - each class has a function:
* char [] GetProtocolName ()
 and on the basis of the protocol:
protocol 1
protocol 2
protocol x...
the user can choose by which class the communication should be handled
my question is as follows:
how in the program - ie after the compilation, and how to save it in the code, before compilation - I can determine that the selected class will be the child X of my virtual class / parent - based on text settings (SELECT USER in this list classes).
The problem is 2 things:
how to list each available class as a child of class A, which are available in the program
how to assign a child - choose one protocol from many - based on what you choose from the list (ie on the basis of * char [])
?
class * communicationProtocol = ?????
I'm brand new in the subject. Thank you for any hint. I do not know what phrase to use, and the phrases I want give me the knowledge I already have.
O! I found something like here:
namespace Ez {
std::shared_ptr<EzGraver> create(QString const& portName, int protocol) {
qDebug() << "instantiating EzGraver on port" << portName << "with protocol version" << protocol;
std::shared_ptr<QSerialPort> serial{new QSerialPort(portName)};
serial->setBaudRate(QSerialPort::Baud57600, QSerialPort::AllDirections);
serial->setParity(QSerialPort::Parity::NoParity);
serial->setDataBits(QSerialPort::DataBits::Data8);
serial->setStopBits(QSerialPort::StopBits::OneStop);
if(!serial->open(QIODevice::ReadWrite)) {
qDebug() << "failed to establish a connection on port" << portName;
qDebug() << serial->errorString();
throw std::runtime_error{QString{"failed to connect to port %1 (%2)"}.arg(portName, serial->errorString()).toStdString()};
}
switch(protocol) {
case 1:
return std::make_shared<EzGraverV1>(serial);
case 2:
return std::make_shared<EzGraverV2>(serial);
case 3:
return std::make_shared<EzGraverV3>(serial);
default:
throw std::invalid_argument{QString{"unsupported protocol '%1' selected"}.arg(protocol).toStdString()};
}
}
#ifndef EZGRAVERV1_H
#define EZGRAVERV1_H
#include <QSerialPort>
#include <memory>
#include "ezgraver.h"
namespace Ez {
struct EzGraverV1 : EzGraver {
using EzGraver::EzGraver;
/*! Moves the engraver up. */
void up() override;
...
on
https://github.com/camrein/EzGraver/blob/master/EzGraverCore/factory.cpp
it's almost what I was looking for ... i.e. it does not show the index and i understand that i need to specify this index, but i can see a construction on how to create several protocols :)
thank you for all the answers!
You could use a mix of constexpr function and std::conditional.
Add a getter function to your classes that will return the class type (or name if you want to):
constexpr static const char *getType()
{
return 0; // You should use enum here
}
Then add a constexpr function that will check for this value (using a switch case for example):
constexpr bool isType()
{
return Test::getType() == 0; // Do a real comparison with a templated function for example
}
Then use std::conditional to get your type:
typedef std::conditional<isType(), int, double>::type Type1;
This code is not to be used like that, but as an example to help you understand what I mean
A common approach is to use a "registry". You define a map from the name (that you could ask to the user or read from a file) and a function that creates the appropriate child.
The following is a toy but complete example; note how main doesn't need to know the list of all possible derived classes and still can create an object of a given derived class type from its name:
#include <iostream>
#include <map>
#include <string>
struct Shape {
virtual void draw() = 0;
virtual ~Shape() {};
};
struct Triangle : Shape {
virtual void draw() override { std::cout << "I'm a triangle!\n"; }
};
struct Circle : Shape {
virtual void draw() override { std::cout << "I'm a circle!\n"; }
};
std::map<std::string, Shape *(*)()> registry{
{"triangle", []()->Shape* { return new Triangle; }},
{"circle", []()->Shape* { return new Circle; }}
};
int main(int argc, const char *argv[]) {
if (argc != 2) {
std::cout << "You need to choose the shape type:\n";
for (auto& i : registry) {
std::cout << " " << i.first << "\n";
}
} else {
auto i = registry.find(argv[1]);
if (i == registry.end()) {
std::cout << "Unknown shape type\n";
} else {
Shape *s = i->second();
s->draw();
delete s;
}
}
return 0;
}
One subtle detail you should pay attention to is that if the derived classes are defined in other compilation units and their registration is also done during static initialization of those units there is formally the risk that the linker will not consider those classes at all unless there is some explicit reference to the units. In other words, suppose you have:
/// File a.cpp
#include "base.h"
#include "registry.h"
struct DerivedA : Base {
...
};
static int init_a = [](){
registry["a"] = []()->Base* { return new DerivedA; };
return 1;
}();
and similar files for all other derived classes.
Then the C++ standard says that it is possible that those classes will not be registered even if you compile them and link them in the program.
This happens because init_a initialization can be delayed until the first access to any object in the compilation unit is done. But if init_a is not initialized then there's no way someone can access this class because the name will not be in the registry. There's no guarantee that dynamic initialization of static duration objects is performed before the start of main, you're only guaranteed that it is performed before any use of any symbol in that compilation unit.
Unfortunately there is no portable atstart() in C++.
In other words using self-registering modules (i.e. no reference to any symbol in those compilation units is present anywhere else in the program) is not portable C++. It may work but there's no such a guarantee.
To be safe you should just register all the classes explicitly.

Omitting parameter with default value in a subclass function override

I am writing an interface for several I/O classes.
There is a function that looks for information in different kinds of files (sometimes html, sdb, txt, ...):
bool Search(std::string file, std::string field)
However, one of these requires an additional parameter to complement the SQL query. In this case the sdb needs to specify in what table the field is located.
I am trying something like the following (it does not compile, I am aware):
class fileIO{
public:
virtual ~FileIO(){};
virtual bool Search(std::string file, std::string field,
std::string additional = 0 /* for sdb only */) = 0;
}
class readHTML : fileIO{
public:
bool Search(std::string file, std::string field); //does NOT override virtual method
Is there anything that can give me the behavior I am looking for?
Is such strategy according to C++ standards?
What else could I add to replace such enforcement on the interface?
I am sorry if the title is misleading, I am looking for an alternative with that behavior. I could not find it so far.
You don't need it, I'd say.
At the caller site, there is only two possibilities: you know your specific fileIO instance is a sdbIO or you don't. If you do, you can call an overloaded version of Search defined in sdbIO which takes this additional info. If you don't, you don't and sdbIO::Search should be defined in terms of its overloaded version.
struct fileIO
{
virtual bool Search(std::string file, std::string field) = 0;
}
struct sdbIO : fileIO
{
bool Search(std::string file, std::string field, std::string additional);
bool Search(std::string file, std::string field) override
{
Search(file, field, "");
}
};
At the caller site:
void f(fileIO& io)
{
// I know this is a sdb:
dynamic_cast<sdbIO&>(io).Search("/file", "text", "WHERE answer=42");
// I don't
io.Search("/file", "text");
}
notes: do you really need a copy of those strings?
You can hide the virtual function in the non-public interface and make the public interface (with the default argument) non-virtual.
struct Interface
{
...
// public interface calls the abstract members.
bool Search(string const&a, string const&b, string const&c = "")
{
if(c.empty() && need_third_string())
throw runtime_error("search requires an additional string argument");
return search(a,b,c);
}
protected:
virtual bool need_third_string() const = 0;
virtual bool search(string const&, string const&, string const&) const=0;
};
with obvious derivations:
struct A : Interface
{
protected:
bool need_third_string() const override
{ return false; }
bool search(string const&a, string const&b, string const&) const override
{ /* search ignoring third argument */ }
};
struct B : Interface
{
protected:
bool need_third_string() const override
{ return true; }
bool search(string const&a, string const&b, string const&c) const override
{ /* search ignoring using all 3 arguments */ }
};
I don't see any problem with above two way to handle things. Still, I have just one more.
#include<bits/stdc++.h>
#include <stdexcept>
using namespace std;
typedef struct
{
std::string arg1;
std::string arg2;
std::string arg3;
} Param;
class FileIO{
public:
virtual ~FileIO(){};
virtual void Search(Param param) = 0;
};
class ReadHTML : public FileIO{
public:
void Search(Param param)
{
if(param.arg3.length() > 0) // Some logic to handle things here.
search3(param.arg1, param.arg2, param.arg3);
else
throw std::runtime_error("Bad call with param");
}
private:
void search3(std::string arg1, std::string arg2, std::string arg3)
{
std::cout << " I am called with Html::Search3" << std::endl;
}
};
class ReadTxt : public FileIO{
public:
void Search(Param param)
{
if(param.arg1.length() && param.arg2.length()) // Some logic to handle things here.
search2(param.arg1, param.arg2);
else
throw std::runtime_error("Bad call with param");
}
private:
void search2(std::string arg1, std::string arg2)
{
std::cout << " I am called with Txt::Search2" << std::endl;
}
};
// Driver program to test above function
int main()
{
FileIO *io = new ReadHTML();
Param paramHtml = {"a", "b", "c"};
io->Search(paramHtml); // Put some try .. catch
Param paramTxt = {"a", "b"};
io = new ReadTxt(); // Put some try...catch
io->Search(paramTxt);
return 0;
}

C++ pointer to class method

I want to do something like this:
struct CLI_Command{
CLI_Command(char* s, void (*h)(void)){
command_string = s;
handler = h;
}
char* command_string;
void (*handler)(void);
};
class CLI {
public:
CLI();
private:
CLI_Command cli_table[NO_CLI_COMMANDS] = {
CLI_Command("Command1", handler1),
CLI_Command("Command2", handler2)
};
void handler1(){};
void handler2(){};
};
I know that I need something similar to CLI::*handler, but I can't get the syntax right. I keep running into errors like this:
"error: no matching function for call to 'CLI_Command::CLI_Command(const char [4], <unresolved overloaded function type>)"
This illustrates the correct syntax:
class CLI;
struct CLI_Command
{
CLI_Command(char* s, void (CLI::*h)(void))
{
command_string = s;
handler = h;
}
char* command_string;
void (CLI::*handler)(void);
void raise( CLI* the_cli ) { return (the_cli->*handler)(); }
};
class CLI
{
public:
CLI();
private:
static CLI_Command cli_table[NO_CLI_COMMANDS];
void handler1(){};
void handler2(){};
};
CLI::CLI_Command cli_table[NO_CLI_COMMANDS] = {
{ "Command1", &CLI::handler1 },
{ "Command2", &CLI::handler2 }
};
Names of member functions do not decay to pointer-to-member. You must use & explicitly, and a qualified name, when creating a pointer-to-member.
In addition to other answers, another option is to use std::function together with std::bind():
struct CLI_Command{
...
std::function<void> handler;
};
class CLI {
...
CLI_Command cli_table[NO_CLI_COMMANDS] = {
{ "Command1", std::bind(&CLI::handler1, this) },
{ "Command2", std::bind(&CLI::handler2, this) }
};
void handler1(){};
void handler2(){};
};
void handler1(){}
void handler2(){}
are member functions of CLI. The correct way to "address to" them is &CLI::handler1 and not handler1. However then, they won't be accepted by void (*h)(void), which would need to be changed to void (CLI::*h)(void). But that is probably not what you want.
Maybe consider reading about std::function for type erasure, or make your handler1/handler2 static.
You should use the syntax for a pointer to class member instead of the syntax for a loose function pointer.
class CLI;
struct CLI_Command{
CLI_Command(char* s, void (CLI::*h)(void)){
command_string = s;
handler = h;
}
char* command_string;
void (CLI::*handler)(void);
};
In addition, make sure you call the function through the pointer of the current CLI class;
void CLI::process(char *cmd) {
CLI_Command command* = /* lookup the command */
this->(command->handle)();
}
To get it working, make your methods static
static void handler1(){};
static void handler2(){};
Whatever consequences (read here please, for more detailed info) this will have :-( .

Get list of functions in a namespace at runtime?

Is it possible to get a list of functions in a certain namespace or all functions in a program at runtime?
I have a function pointer map and I need to add commands on my own to it, but I thought: why not create a namespace and let the program do the work at runtime?
something like(pseudocode):
typedef bool (*command)(void);
namespace Commands
{
bool Start(void)
{
return true;
}
bool End(void)
{
return true;
}
};
std::map<std::string,command> CommandMap;
main()
{
for(each function in namespace Commands)
{
CommandMap[std::string(function_name)] = function;
}
CommandMap["Start"]();
CommandMap["End"]();
return 0;
}
instead of
std::map<std::string,command> CommandMap;
main()
{
CommandMap["Start"] = Commands::Start;
CommandMap["End"] = Commands::End;
//list of thousands of other commands......
CommandMap["Start"]();
CommandMap["End"]();
return 0;
}
Is this possible to achieve in C++ or C++11? Or any alternatives to my goal?
No (it has to be 30 characters).
EDIT: This goes along with my comment about how much control you have. You could redefine all of your functions as functors, and have the constructor register itself with some array. Your base class would look like this:
EDIT2: read the comment about all functions having same arguments and return types, makes it a little cleaner.
class myFunctorBaseClass
{
public:
myFunctorClass () : {//register myself, no duplicates}
virtual int operator () (int);//Whatever types you want
};
class myFunctor: public myFunctorBaseClass //Define as many of these as you need
{
public:
int operator() (int y) { return y; } // Define this as whatever you want
}
This obviously would depend on the objects being constucted, but assuming they all were as an initialization step, this would get you what you want.
NOTE: This may be incomplete/not compile. I just kinda wrote this off the top of my head, but it should be close. The reference you want is "functors" if you have questions about how this works.
Consider something like:
class CommandCollection
{
...
void register_command(Command*, string);
map<string, Command*> m_command_map;
}
class Command
{
...
virtual do_command(...) = 0;
}
class EachCommand : public Command
{
EachCommand() { CommandCollection::instance().register_command(this, my_name); }
...
virtual do_command(...);
}
EachCommand each_command_inst;
The Command base class has a virtual to do a command. Each derived type implements the command (you could try overloading the () operator to make them look more like functions).
Each derived Command registers itself with the CommandCollection, so it can be known in a central location. If you want to associate the commands by string (seems good if a user is typing them in), then that would be the key in the map.
As mentioned elsewhere, names (in C and C++, other languages may/do differ on this point) only really exist as part of the source-code. Once compiled, the names cease to have any meaning in C and C++.
One could, however, consider some sort of structure like this:
class CommandBase
{
virtual bool doCommand() = 0;
virtual std::string name() = 0;
virtual ~CommandBase() {}
};
class StartCommand : public CommandBase
{
bool doCommand() { ...; return true }
std::string name() { return "Start"; }
};
void RegisterCommand(CommandBase *cmd)
{
CommandMap[cmd->name] = cmd;
}
...
StartCommand start;
...
void someFunction()
{
RegisterCommand(&start);
}
I'll probably get a downvote for mentioning macros, because these are evil - don't use this if you are a purist that don't like macros.
#define CMD(x) CommandMap[#x] = Command::x
CMD(start);
CMD(end);
There are certainly other variants, and someone who knows templates may well come up with something that does this using templates.

raw function pointer from a bound method

I need to bind a method into a function-callback, except this snippet is not legal as discussed in demote-boostfunction-to-a-plain-function-pointer.
What's the simplest way to get this behavior?
struct C {
void m(int x) {
(void) x;
_asm int 3;
}};
typedef void (*cb_t)(int);
int main() {
C c;
boost::function<void (int x)> cb = boost::bind(&C::m, &c, _1);
cb_t raw_cb = *cb.target<cb_t>(); //null dereference
raw_cb(1);
return 0;
}
You can make your own class to do the same thing as the boost bind function. All the class has to do is accept the function type and a pointer to the object that contains the function. For example, this is a void return and void param delegate:
template<typename owner>
class VoidDelegate : public IDelegate
{
public:
VoidDelegate(void (owner::*aFunc)(void), owner* aOwner)
{
mFunction = aFunc;
mOwner = aOwner;
}
~VoidDelegate(void)
{}
void Invoke(void)
{
if(mFunction != 0)
{
(mOwner->*mFunction)();
}
}
private:
void (owner::*mFunction)(void);
owner* mOwner;
};
Usage:
class C
{
void CallMe(void)
{
std::cout << "called";
}
};
int main(int aArgc, char** aArgv)
{
C c;
VoidDelegate<C> delegate(&C::CallMe, &c);
delegate.Invoke();
}
Now, since VoidDelegate<C> is a type, having a collection of these might not be practical, because what if the list was to contain functions of class B too? It couldn't.
This is where polymorphism comes into play. You can create an interface IDelegate, which has a function Invoke:
class IDelegate
{
virtual ~IDelegate(void) { }
virtual void Invoke(void) = 0;
}
If VoidDelegate<T> implements IDelegate you could have a collection of IDelegates and therefore have callbacks to methods in different class types.
Either you can shove that bound parameter into a global variable and create a static function that can pick up the value and call the function on it, or you're going to have to generate per-instance functions on the fly - this will involve some kind of on the fly code-gen to generate a stub function on the heap that has a static local variable set to the value you want, and then calls the function on it.
The first way is simple and easy to understand, but not at all thread-safe or reentrant. The second version is messy and difficult, but thread-safe and reentrant if done right.
Edit: I just found out that ATL uses the code generation technique to do exactly this - they generate thunks on the fly that set up the this pointer and other data and then jump to the call back function. Here's a CodeProject article that explains how that works and might give you an idea of how to do it yourself. Particularly look at the last sample (Program 77).
Note that since the article was written DEP has come into existance and you'll need to use VirtualAlloc with PAGE_EXECUTE_READWRITE to get a chunk of memory where you can allocate your thunks and execute them.
#include <iostream>
typedef void(*callback_t)(int);
template< typename Class, void (Class::*Method_Pointer)(void) >
void wrapper( int class_pointer )
{
Class * const self = (Class*)(void*)class_pointer;
(self->*Method_Pointer)();
}
class A
{
public:
int m_i;
void callback( )
{ std::cout << "callback: " << m_i << std::endl; }
};
int main()
{
A a = { 10 };
callback_t cb = &wrapper<A,&A::callback>;
cb( (int)(void*)&a);
}
i have it working right now by turning C into a singleton, factoring C::m into C::m_Impl, and declaring static C::m(int) which forwards to the singleton instance. talk about a hack.