C++ runtime type switching (avoiding switch) - c++

I've been into C++ for some years but I have not found yet the solution to a problem I constantly have. Know how to solve it would be awesome.
What I have at the moment is:
// Client code:
switch(currentEnumValue)
{
case MyEnum::kValue01:
processData<MyEnum::kValue01>(data);
break;
case MyEnum::kValue02:
processData<MyEnum::kValue02>(data);
break;
default:
LOG("Invalid command");
break;
}
// Declarations
enum class MyEnum {kValue01, kValue02};
class MyClass
{
// code
template <MyEnum> void processData(char*); /* Implemented somewhere else */
}
template <> void MyClass::processData<MyEnum::kValue01>(char* data); /* Implemented somewhere else */
MyClass <> void MyClass::processData<MyEnum::kValue02>(char* data); /* Implemented somewhere else */
I would like to remove the switch because of many reasons. Instead of it I would need something like: processData<runtime-decltype(currentEnumValue)>(data);
I know about typeid and about not mixing compile time and runtime together... but despite this, I would like to find some solution anyway, preferably excluding macros.

This class makes a jump table for a given Enum up to a certain count size based off constructing some template and invoking it with the supplied args. It assumes the enum values start at 0, and go to Count-1.
template<class Enum, Enum Count, template<Enum>class Z>
struct magic_switch {
// return value of a call to magic_switch(Args...)
template<class...Args>
using R = std::result_of_t<Z<Enum(0)>(Args...)>;
// A function pointer for a jump table:
template<class...Args>
using F = R<Args...>(*)(Args&&...);
// Produces a single function pointer for index I and args Args...
template<size_t I, class...Args>
F<Args...> f() const {
using ret = R<Args...>;
return +[](Args&&...args)->ret{
using Invoke=Z<Enum(I)>;
return Invoke{}(std::forward<Args>(args)...);
};
}
// builds a jump table:
template<class...Args, size_t...Is>
std::array<F<Args...>,size_t(Count)>
table( std::index_sequence<Is...> ) const {
return {{
f<Is, Args...>()...
}};
}
template<class...Args>
R<Args...> operator()(Enum n, Args&&...args) {
// a static jump table for this case of Args...:
static auto jump=table<Args...>(std::make_index_sequence<size_t(Count)>{});
// Look up the nth entry in the jump table, and invoke it:
return jump[size_t(n)](std::forward<Args>(args)...);
}
};
then if you have an enum:
enum class abc_enum { a, b, c, count };
and a function object template:
template<abc_enum e>
struct stuff {
void operator()() const {
std::cout << (int)e << '\n';
}
};
you can dispatch:
magic_switch<abc_enum, abc_enum::count, stuff>{}(abc_enum::b);
in any case, within the template stuff, you get the enum value as a compile time constant. You call it with a run time constant.
Overhead should be similar to a switch statement, or a vtable call, depending on what the compiler does optimization wise.
live example.
Note that setting Enum to std::size_t is valid.
In C++11 you need make_index_sequence and index_sequence:
template<size_t...>
struct index_sequence {};
namespace details {
template<size_t Count, size_t...szs>
struct sequence_maker : sequence_maker<Count-1, Count-1, szs...> {};
template<size_t...szs>
struct sequence_maker<0,szs...> {
using type = index_sequence<szs...>;
};
}
template<size_t Count>
using make_index_sequence=typename details::sequence_maker<Count>::type;
template<class...Ts>
using index_sequence_for=make_index_sequence<sizeof...(Ts)>;
and this alias:
template<class Sig>
using result_of_t=typename std::result_of<Sig>::type;
then strip std:: off their use in the above code.
live example.

Boost variant does something like what you are doing. It lets you replace switch statements with a template based contruct that can check that all cases are defined at compile-time, but then select one at run-time.
e.g.,
using namespace boost;
using Data = variant<int, double>;
struct ProcessDataFn: static_visitor<void>
{
char* data;
void operator()(int& i)
{
// do something with data
}
void operator()(double& d)
{
// do something else
}
};
void processData(char* data, Data& dataOut)
{
apply_visitor(ProcessDataFn{data}, dataOut);
}
void example(char * data)
{
Data d = 0;
processData(data, d); // calls first overload of operator()
Data d = 0.0;
processData(data, d); // calls second overload
}

To expand on my comment, ideally we'd have compile-time reflection and be able to write a generic dispatch function. In its absence, one option is to unfortunately use macros to do that for you using the X Macro pattern:
#define LIST_OF_CASES \
X_ENUM(kValue0) \
X_ENUM(kValue1) \
X_ENUM(kValue2)
enum MyEnum
{
# define X_ENUM(a) a,
LIST_OF_CASES
# undef X_ENUM
};
void dispatch(MyEnum val)
{
switch (val)
{
# define X_ENUM(a) case a: processData<a>(); break;
LIST_OF_CASES
# undef X_ENUM
default:
// something's really wrong here - can't miss cases using this pattern
}
}
One benefit of this approach is that it scales to large numbers of enumerations, it gets really hard to omit a case, and that you can attach extra information by using a multi-argument X_ENUM macro.
I know you said you'd like to avoid macros, but the alternative without virtual functions then is to have some sort of a static table of function pointers indexed by the enum, and that is just a virtual function in disguise (with admittedly lower overhead, but still suffering the cost of an indirect function call).

Related

Dynamic dispatch based on Enum value

Lets say I'm trying to write multiple handlers for multiple message types.
enum MESSAGE_TYPE { TYPE_ZERO, TYPE_ONE, TYPE_TWO, TYPE_THREE, TYPE_FOUR };
One solution might be
void handler_for_type_one(...){ ... }
void handler_for_type_two(...){ ... }
...
switch(message_type){
case TYPE_ONE: handler_for_type_one(); break;
case TYPE_TWO: handler_for_type_two(); break;
...
And yeah, that would work fine. But now I want to add logging that wraps each of the handlers. Let's say a simple printf at the beginning / end of the handler function (before and after is fine too).
So maybe I do this:
template<MESSAGE_TYPE>
void handler() {
std::printf("[default]");
}
template<> void handler<TYPE_ONE>() {
std::printf("[one]");
}
template<> void handler<TYPE_TWO>() {
std::printf("[two]");
}
template<> void handler<TYPE_THREE>() {
std::printf("[three]");
}
int main()
{
std::printf("== COMPILE-TIME DISPATCH ==\n");
handler<TYPE_ZERO>();
handler<TYPE_ONE>();
handler<TYPE_TWO>();
handler<TYPE_THREE>();
handler<TYPE_FOUR>();
}
And it works how I'd expect:
== COMPILE-TIME DISPATCH ==
[default][one][two][three][default]
When the message-type is known at compile time, this works great. I don't even need that ugly switch. But outside of testing I won't know the message type and even if I did, wrap_handler (for the logging) "erases" that, requiring me to use the switch "map".
void wrap_handler(MESSAGE_TYPE mt) {
std::printf("(before) ");
switch (mt) {
case TYPE_ZERO: handler<TYPE_ZERO>(); break;
case TYPE_ONE: handler<TYPE_ONE>(); break;
case TYPE_TWO: handler<TYPE_TWO>(); break;
case TYPE_THREE: handler<TYPE_THREE>(); break;
//case TYPE_FOUR: handler<TYPE_FOUR>(); break; // Showing "undefined" path
default: std::printf("(undefined)");
}
std::printf(" (after)\n");
}
int main()
{
std::printf("== RUNTIME DISPATCH ==\n");
wrap_handler(TYPE_ZERO);
wrap_handler(TYPE_ONE);
wrap_handler(TYPE_TWO);
wrap_handler(TYPE_THREE);
wrap_handler(TYPE_FOUR);
}
== RUNTIME DISPATCH ==
(before) [default] (after)
(before) [one] (after)
(before) [two] (after)
(before) [three] (after)
(before) (undefined) (after)
My "goals" for the solution are:
Have the enum value as close to the handler definition as possible -- template specialization like I show above seems to be about the best I can do in this area, but I have no idea.
When adding a message-type/handler, I'd prefer to keep the changes as local/tight as possible. (Basically, I'm looking for any way to get rid of that switch).
If I do need a switch or map, etc., since it'd be far away from the new handler, I'd like a way at compile time to tell whether there's a message type (enum value) without a corresponding switch case. (Maybe make the switch a map/array? Not sure if you can get the size of an initialized map at compile time.)
Minimize boilerplate
The other solution that seems obvious is a virtual method that's overridden in different subclasses, one for each message type, but it doesn't seem like there's a way to "bind" a message type (enum value) to a specific implementation as cleanly as the template specialization above.
Just to round it out, this could be done perfectly with (other languages) decorators:
#handles(MESSAGE_TYPE.TYPE_ZERO)
def handler(...):
...
Any ideas?
One way I'd get rid of the manual switch statements is to use template recursion, as follows. First, we create an integer sequence of your enum class, like so:
enum MESSAGE_TYPE { TYPE_ZERO, TYPE_ONE, TYPE_TWO, TYPE_THREE, TYPE_FOUR };
using message_types = std::integer_sequence<MESSAGE_TYPE, TYPE_ZERO, TYPE_ONE, TYPE_TWO, TYPE_THREE, TYPE_FOUR>;
Second, let's change slightly the handler and make it a class with a static function:
template <MESSAGE_TYPE M>
struct Handler
{
// replace with this whatever your handler needs to do
static void handle(){std::cout << (int)M << std::endl;}
};
// specialise as required
template <>
struct Handler<MESSAGE_TYPE::TYPE_FOUR>
{
static void handle(){std::cout << "This is my last message type" << std::endl;}
};
Now, with these we can easily use template recursion to create a generic switch map:
template <class Sequence>
struct ct_map;
// specialisation to end recusion
template <class T, T Head>
struct ct_map<std::integer_sequence<T, Head>>
{
template <template <T> class F>
static void call(T t)
{
return F<Head>::handle();
}
};
// recursion
template <class T, T Head, T... Tail>
struct ct_map<std::integer_sequence<T, Head, Tail...>>
{
template <template <T> class F>
static void call(T t)
{
if(t == Head) return F<Head>::handle();
else return ct_map<std::integer_sequence<T, Tail...>>::template call<F>(t);
}
};
And use as follows:
int main()
{
ct_map<message_types>::call<Handler>(MESSAGE_TYPE::TYPE_ZERO);
ct_map<message_types>::call<Handler>(MESSAGE_TYPE::TYPE_THREE);
ct_map<message_types>::call<Handler>(MESSAGE_TYPE::TYPE_FOUR);
}
If now, you want to create your wraphandler, you can do this:
template <MESSAGE_TYPE M>
struct WrapHandler
{
static void handle()
{
std::cout << "Before" << std::endl;
Handler<M>::handle();
std::cout << "After" << std::endl;
}
};
int main()
{
ct_map<message_types>::call<WrapHandler>(MESSAGE_TYPE::TYPE_THREE);
}
Live code here
The way I understand it, a function pointer may be what you need.
Going from your example, the code would be like this:
template<MESSAGE_TYPE>
void handler() {
std::printf("[default]");
}
template<> void handler<TYPE_ONE>() {
std::printf("[one]");
}
template<> void handler<TYPE_TWO>() {
std::printf("[two]");
}
template<> void handler<TYPE_THREE>() {
std::printf("[three]");
}
void wrap_handler(void (*handler)()) {
std::printf("(before) ");
if (!handler)
std::printf("(undefined)");
else
handler();
std::printf(" (after)\n");
}
int main()
{
std::printf("== COMPILE-TIME DISPATCH ==\n");
handler<TYPE_ZERO>();
handler<TYPE_ONE>();
handler<TYPE_TWO>();
handler<TYPE_THREE>();
handler<TYPE_FOUR>();
std::printf("\n\n");
std::printf("== RUNTIME DISPATCH ==\n");
wrap_handler(TYPE_ZERO);
wrap_handler(TYPE_ONE);
wrap_handler(TYPE_TWO);
wrap_handler(TYPE_THREE);
wrap_handler(TYPE_FOUR);
}
The function pointer mirrors the prototype of the function (meaning all calls need to be compatible).
In order to pass an argument, the function would change to:
void wrap_handler(void (*handler)(ArgumentType), const ArgumentType &arg) {
std::printf("(before) ");
if (!handler)
std::printf("(undefined)");
else
handler(arg);
std::printf(" (after)\n");
}
A way around this would be to use std::function (C++11).
void wrap_handler(std::function<> handler) {
std::printf("(before) ");
if (!handler)
std::printf("(undefined)");
else
handler();
std::printf(" (after)\n");
}
Possible ways to call this include:
wrap_handler(&functionWithoutArguments);
wrap_handler(std::bind(functionWithArgument, someArgument);
wrap_handler([=](){ LambdaCode; });
etc.
This is a common problem for all applications receiving messages or events.
However, in C++ the switch or some kind of table of handlers is the best you can do. The reason is that the value of the enum only exists at run-time, therefore you cannot make that decision at compile time.
Other languages, like Python, can provide the solution you are looking for, because they are interpreted languages, so compile time and run-time are the same.
Boost asio is good example of how you can hide the switch, but my experience is that hiding it is not as good as you think at the first place.
When you need to debug your code or someone else has to find the handler which belongs to a certain event, or somehow, you have to check if the handler is registered you need to know, where the switch is, place a break point there, or log the incoming messages. This is much more difficult in systems like asio.
C++ requires the exact function signature to be figured out at compile time. This does include determining template parameters. You won't be able to get rid of some logic that determines the exact operation to execute, whether you're creating a map-like data structure for this or keep it a switch. If you're just worried about accidentally leaving out some enum constant in the switch or about the boilerplate code this may be the time to get the preprocessor involved.
#ifdef MESSAGE_TYPES
# error macro name conflict for MESSAGE_TYPES may result in errors
#endif
// x is a function-like macro that takes 1 parameter (2, if you want the constants to assigned a specific value)
#define MESSAGE_TYPES(x) \
x(TYPE_ZERO) \
x(TYPE_ONE) \
x(TYPE_TWO) \
x(TYPE_THREE) \
x(TYPE_FOUR)
#ifdef MESSAGE_TYPE_ENUM_CONSTANT
# error macro name conflict for MESSAGE_TYPE_ENUM_CONSTANT may result in errors
#endif
#define MESSAGE_TYPE_ENUM_CONSTANT(c) c,
enum MESSAGE_TYPE { MESSAGE_TYPES(MESSAGE_TYPE_ENUM_CONSTANT) };
#undef MESSAGE_TYPE_ENUM_CONSTANT
template<MESSAGE_TYPE>
void handler() {
std::printf("[default]");
}
template<> void handler<TYPE_ONE>() {
std::printf("[one]");
}
template<> void handler<TYPE_TWO>() {
std::printf("[two]");
}
template<> void handler<TYPE_THREE>() {
std::printf("[three]");
}
void wrap_handler(MESSAGE_TYPE mt) {
std::printf("(before) ");
#ifdef HANDLER_CALL_SWITCH_CASE
# error macro name conflict for HANDLER_CALL_SWITCH_CASE may result in errors
#endif
#define HANDLER_CALL_SWITCH_CASE(c) case c: handler<c>(); break;
switch (mt) {
MESSAGE_TYPES(HANDLER_CALL_SWITCH_CASE);
default:
std::printf("(undefined)");
break;
}
#undef HANDLER_CALL_SWITCH_CASE
std::printf(" (after)\n");
}
#undef MESSAGE_TYPES

C++ Call functions based on enum values

I have this code
class Foo {
private:
enum class Heuristic {
ONE,
TWO,
THREE
};
Heuristic h;
void select();
};
void Foo::select() {
if (h == Heuristic::ONE)
selectONE();
else if (h == Heuristic::TWO)
selectTWO();
else
selectTHREE();
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
Based on the value of heuristic I want to call a specific function in select(). I don't know the value of heuristic at compile time, as it depends on user input. To avoid the conditional check in select() I would like to use templates. How can I accomplish this?
As it depends on runtime values there is no way to get rid of some sort of runtime checks. Which are either done by you with if, switch, … or by a container like std::map, std::unordered_map
Due to that, your concern there should be readability and maintainability.
I would - like already suggested in a comment - use switch instead of if, but not because the compiler can optimize it better (IMHO the compiler will be able to generate the same code for both), but to allow the static analyzer to warn you about not used enums.
If the question is about performance concerns, then this should only be a problem if you call these functions at a high frequency. So if this is the case you could create a template-based entry point to your task, to which you pass the function as template argument based on the user selection:
template<auto SelectedHeuristic>
void Foo::task() {
for( /* … */ ) {
SelectedHeuristic();
}
}
void Foo::select() {
switch(h) {
case Heuristic::ONE:
Foo::task<selectONE>();
break;
case Heuristic::TWO:
Foo::task<selectTWO>();
break;
case Heuristic::THREE:
Foo::task<selectTHREE>();
break;
}
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
To avoid the conditional check in select() [...]
A simple way to avoid all conditional checks (hidden or otherwise) in select() could be to create an array of pointers to your functions. You then look the function up by using its current Heuristic value (which must start at 0 and not have any gaps). If the Heuristic value changes rarely, you can even move the lookup out of select() completely.
Example:
##include <iostream>
void selectONE() { std::cout << "one\n"; };
void selectTWO() { std::cout << "two\n"; };
void selectTHREE() { std::cout << "three\n"; };
using func_ptr_t = void(*)(); // the signature of your functions
class Foo {
public:
enum class Heuristic {
ONE,
TWO,
THREE
};
void set_heuristic(Heuristic); // a function to do the lookup
void select();
private:
Heuristic h;
func_ptr_t current_func; // a pointer to the selected function
};
void Foo::set_heuristic(Heuristic value) {
// a simple map from Heuristic value to function pointer
static const func_ptr_t funcmap[] = {
&selectONE,
&selectTWO,
&selectTHREE,
};
h = value; // perhaps not needed?
// look up the function pointer based on "h"
current_func = funcmap[static_cast<unsigned>(h)];
}
void Foo::select() {
// a pretty fast callsite:
current_func();
}
int main() {
Foo bar;
bar.set_heuristic(Foo::Heuristic::ONE);
bar.select(); // prints "one"
}
define a map<Heuristic, lambdas> where the lambdas are defined as
void and taking no parameters
void f()
then take the user input and get the value of that input key and trigger the lambda

Hash specialization for table of function pointer

Updates in bold
I am writing a hash function for a table of function pointers with the limitation that the structure of the function pointers and function table cannot be modified (i.e. they have been published to third-parties). Based on Can std::hash be used to hash function pointers?, std::hash can be used for function pointers. Adopting that, it yields the following solution.
The tedious part about this solution is that every time we add new APIs to FuncPointers struct, we'd have to modify the hash specialization to add the corresponding change (i.e. hashFunc(hashedValue, pFuncs->func3) ).
I am wondering if there's a better way to implement this hashing of function pointers so continuous modification to the hash specialization can be avoided?
typedef void (*func_type1) (int);
typedef void (*func_type2) (double);
typedef struct FuncPointers
{
func_type1 func1;
func_type2 func2;
...
} FuncPointers;
template <typename T> void hashFunc (size_t & HashedValue, T funcPointer)
{
std::hash<T> hash;
HashedValue ^= hash(funcPointer); // the XOR operator is randomly picked
}
namespace std
{
template<> struct hash<FuncPointers>
{
size_t operator()(FuncPointers *pFuncs)
{
size_t hashedValue = 0;
hashFunc(hashedValue, pFuncs->func1);
hashFunc(hashedValue, pFuncs->func2);
...
return hashedValue;
}
};
}
Start with this: https://stackoverflow.com/a/7115547/1774667
It provides a hash_tuple::hash<Tuple> that is a valid decent quality hasher (with combining and recursion support!) for a std::tuple.
Next, change FuncPointers as follows:
struct FuncPointers:std::tuple<func_type1, func_type2 /*, ...*/> {
// optional:
func_type1 func1() const { return std::get<0>(*this); }
func_type1& func1() { return std::get<0>(*this); }
//...
};
namespace std {
template<>
struct hash<FuncPointers> {
template<typename... Ts>
std::size_t operator()( std::tuple<Ts...> const& funcs ) const {
return hash_tuple::hash<std::tuple<Ts...>>{}(funcs);
}
};
}
which redirects your std::hash<FuncPointers> to invoke hash_tuple::hash<std::tuple<...>> on the parent of FuncPointers. If you do not want to inherit from std::tuple, changing it to a has-a instead of an is-a relationship should be easy.
The optional func() accessors give you closer to the old interface (just requires a () added), but also adds boilerplate.
An alternative would be:
template<unsigned N>
auto func() const->decltype( std::get<N>(*this) ){ return std::get<N>(*this); }
template<unsigned N>
auto& func()->decltype( std::get<N>(*this) ){ return std::get<N>(*this); }
which changes funcPointers.func1 to funcPointers.func<1>(), but gets rid of tonnes of boilerplate when you add a new func, and stays pretty similar to the old interface of funcPointers.
If there is not much code that is using the old interface, using std::get<N>() makes some sense.
If your names are more descriptive than func1 and you only used that for the example, an enumeration of the function names can be used with std::get or func<X> above. If you go with func<X> you can even make it typesafe (force the use of the named functions).
You'd be better off making your FuncPointers a std::tuple<func_type1, func_type2>. Then see this answer on hashing.
BTW, typedef struct FuncPointers { } FuncPointers is a C-ism which has never been necessary in C++.

C++ 11 Template Variable Design [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a lot of subclasses of an abstract class Letter, like A, B, C, D, etc. Letter has an integer ID variable, and every subclass of Letter gets assigned a unique id.
I then have another class, call it Alphabet. Alphabet has an
list<shared_ptr<Letter>>
member. Here is the problem... I would like to elegantly add B's and C's or other subclasses of Letter to particular instances of Alphabets. I think the most convenient way to do this would be to use the integer id of subclass somehow. In other words, I want to be able to have something like Alphabet.addLetter(int id), so if I did alphabet1.add(14), it would somehow add a shared_ptr for class H to the list.
Is there an elegant way to do this, avoiding some huge if statement where that I need to constantly update every time I add or remove one of the B, C, D, E, etc. classes? I'm hoping there's some kind of template-solution, but I'm not very familiar with advanced c++ notions like factories and templates. The naive thing I wanted was some kind of vector/map that converted my ids into class names, so that I could do something like
list.push_back(shared_ptr<classVector(i)>(new classVector(i))
or something like that, though I have no idea if that's possible.
Thanks!
p.s. I just chose the Alphabet example because I didn't want to give unnecessary detail. Obviously I'm not trying to design alphabets in such a silly way, lol.
edit: I'm struggling to make this make sense. My goal is to be able to create new subclasses of Letter very quickly with minimal effort. I would like to avoid having to type out code that looks like...
list.push_back(shared_ptr<X>(...));
every time I make a new letter. Does this make sense at all?
This is pretty hard to follow, but I think what you want is something along the lines of the following:
// where make_unique<> is from C++14 in std:: or like:
template <typename T, typename ... TArgs>
std::unique_ptr<T> make_unique(TArgs &&... args) {
return std::unique_ptr<T>(new T(std::forward<TArgs>(args)...));
}
struct Letter {
virtual ~Letter() { }
virtual void foo() = 0;
};
template <unsigned int N> struct LetterCode; // Note: no default implementation!
struct Alphabet {
// Indexed access, if you'll have 1 of each type max:
std::vector<std::unique_ptr<Letter>> v;
// If you don't need parameters, as mentioned in comments below ...
template <unsigned int N>
void addLetterN() {
if (N > v.size() + 1) { v.resize(N + 1); }
v[N] = make_unique<LetterCode<N>::type>(); // see below ...
}
// If your coding is complete from 0...N, this does the whole shebang.
template <unsigned int N>
void addLettersN() {
addLetters<N - 1>();
addLetterN<N>();
}
template <>
addLettersN<0>() {
addLetterN<0>();
}
};
If you need numeric codes for something like deserialization and never need constructor arguments, you can use a type trait template like follows to statically 'register' the types:
struct B : Letter {
B(int n, bool b, char const *name);
void foo() override;
};
template <> struct LetterCode<2> { using type = B; };
struct C : Letter {
C(double d);
void foo() override;
};
template <> struct LetterCode<3> { using type = C; };
void bar() {
Alphabet a;
a.addLetterN<2>();
a.addLetterN<3>();
// --OR--
a.addLettersN<3>(); // will do 0...3 in one fell swoop.
for (auto &i : a.v) {
if (!i) { continue; } // v is sparse, unlike l
i->foo();
}
If you need generalized constructor argument passing, you can use perfect forwarding, which is designed for cases like this and obviates the need for enum IDs, etc., from older styles of factories:
struct Alphabet {
std::list<std::unique_ptr<Letter>> l;
// variadic factory that chucks new (shared_ptr) objects in the list.
template <typename T, typename ... TArgs>
void addLetter(TArgs && ... args) {
l.push_back(make_unique<T>(std::forward<TArgs>(args)...));
}
};
void baz() {
Alphabet a;
a.addLetter<B>(1, false, "pony");
a.addLetter<C>(2.718281828);
for (auto &i : a.l) {
i->foo(); // can call virtual funcs here all you want ...
}
}
This is relatively easy if I understood you correctly, using what's called a factory-pattern.
If you can list all of the derived types:
Letter header:
struct Letter {
enum LetterEnum {LetterA, LetterB, LetterC, LetterCount};
virtual ~Letter() {} //base types should always have virtual destructor
virtual void foo() = 0;
static std::unique_ptr<Letter> construct(LetterEnum c);
};
Implementation headers:
struct A : Letter {
void foo() override;
};
struct B : Letter {
void foo() override;
};
struct C : Letter {
void foo() override;
};
Letter body:
std::unique_ptr<Letter> Letter::construct(Letter::LetterEnum c)
{
switch(c) {
case Letter::LetterA : return make_unique<A>();
case Letter::LetterB : return make_unique<B>();
case Letter::LetterC : return make_unique<C>();
default: throw ...;
}
}
Usage:
int main() {
char c;
std::cin >> c;
//get a letter of the derived type associated with the letter entered
std::unique_ptr<Letter> ptr = Letter::construct(c);
}
If you can't list all of the derived types:
Allow the derived types to register themselves with the Letter class, and then Letter can use that to create each of the derived types. This way, adding and deleting the derived types involves no changes to any other files. Easy!
struct Letter {
virtual ~Letter() {} //destructor is always virtual when inheretence is involved
....
//this is a "shared" function in the Letter class itself
//it takes a letter, and returns a dynamically allocated instance
//of the derived type corresponding with that letter
static std::unique_ptr<Letter> construct(char c);
//this typedef represents the actual function that returns
//each dynamically allocated derived type
typedef std::function<std::unique_ptr<Letter>()> letter_ctor;
//this is a "shared" function in the Letter class itself
//it takes a letter, and a function that creates derived types,
//and saves them inside the container ctors
static bool register(char c, letter_ctor func);
private:
//this is a "shared" member in the Letter class.
//There is only one shared by all of the Letters. Like a global.
//When you give it a letter, it gives you a function.
//and is VERY fast for large numbers of entries
static std::unordered_set<char,letter_ctor> ctors;
};
and in your implementation file:
//here's the function that derived types register themselves with
//pretty straightforward, just inserts the pair into the unordered_map
bool Letter::register(char c, Letter::letter_ctor func)
{return Letter::ctors.insert(std::make_pair(c,std::move(func))).second;}
//and here's the function that creates the derived types
//it checks if the letter is in the unordered_map
//if the letter isn't there, it throws an exception
//otherwise, it calls the function associated with that letter
//which creates the derived type on the heap, and returns a pointer to it
std::unique_ptr<Letter> Letter::construct(char c)
{
auto it = Letter::ctors.find(c);
if (it == Letter::ctors.end())
throw ...;
return it->second(); //construct that letter
}
and then your derived types do this:
//you know this part
struct LetterA : public Letter
{
....
};
//derived types have to register themselves:
//this is a global, so when the program loads, it automatically calls this
//even before main runs*
//it registers the letter 'A' and a function that creates a LetterA class on the heap
static bool registerA = Letter::register('A', [](){return make_unique<LetterA>();});
and then you can easily create arbirary derived types!
int main() {
char c;
std::cin >> c;
//get a letter of the derived type associated with the letter entered
std::unique_ptr<Letter> ptr = Letter::construct(c);
}
*It doesn't always get called before main. If you have problems, put an bool init_A(); in the A header, and bool init_A(){return true;} in the A implementation file, and in your main file have static bool AInit=init_A(); which should force it. This is almost never needed in practice though.
As a side note, these depend on having a make_unique, which should have been in C++11, but was left out due to oversight. It will be in C++14. In the meantime, use this:
template<class T, class...Us>
std::unique_ptr<T> make_unique(Us&&...us)
{return std::unique_ptr<T>(new T(std::forward<Us>(us)...));}
My understanding is that you want to create a instance of one of the classes, dependend on an id which relates to the class from which an instance should be created.
If so, please have a look for factory pattern. There are a lot of factory implementations, also based on template recursive expansion of a typelist.
Pseudo Code:
Factory<A,B,C,D> fac; // the list must be changed, if some more classes comes and goes
id_type id;
list<base> l;
l.push_back=fac.Create(id);
It is also quite simple to implement such a class yourself.
The goal is simple: create the function factories that returns an array of Alphabet makers.
The index of the letter and the index into the array will be the same.
Ideally, we want to auto-generate said index without having to manually set it.
#include <memory>
#include <vector>
#include <iostream>
template<class T>using Type=T;
template<class...Ts>struct types:std::integral_constant<unsigned,sizeof...(Ts)>
{typedef types type;};
template<class T,class types>struct index_of;
template<class T,class T0, class...Ts>struct index_of<T,types<T0,Ts...>>:
std::integral_constant<unsigned,index_of<T,types<Ts...>>::value+1>
{};
template<class T,class...Ts>struct index_of<T,types<T,Ts...>>:
std::integral_constant<unsigned,0>
{};
template<unsigned,class types>struct type_at;
template<unsigned N, class T,class...Ts>struct type_at<N,types<T,Ts...>>:
type_at<N-1,types<Ts...>> {};
template<class T,class...Ts>struct type_at<0,types<T,Ts...>>{
typedef T type;
};
template<unsigned N,class types>
using type_at_t=typename type_at<N,types>::type;
template<template<class>class Target,unsigned N,class types>
struct nth_apply;
template<template<class>class Target,unsigned N,class...Ts>
struct nth_apply<Target,N,types<Ts...>>{
typedef Target<type_at_t<N,types<Ts...>>> type;
};
template<template<class>class Target,unsigned N,class types>
using nth_apply_t=typename nth_apply<Target,N,types>::type;
This is the type that produces the function pointers for us:
template<class T>struct shared_maker{
template<class...Args>
std::shared_ptr<T> operator()(Args&&...args)const{
return std::make_shared<T>(std::forward<Args>(args)...);
}
template<class R, class... Args>
operator Type<R(Args...)>*() const{
return [](Args... args)->R{
return shared_maker{}(std::forward<Args>(args)...);
};
}
};
Here is what we do for the actual letter types. We forward declare them:
struct A; struct B; // etc
Stick them into a list of types:
typedef types<A,B> Alphabet_Types;
Now, our simple test Alphabet type:
struct Alphabet {
virtual unsigned get_index() const = 0;
};
And a CRTP helper that gets the index of the letter from its offset into the list of types! The virtual get_indexes is just for debugging:
template<class D>
struct Letter:Alphabet{
static const unsigned index = index_of<D, Alphabet_Types>::value;
virtual unsigned get_index() const override { return index; }
};
Now the signature of our array-producer:
typedef std::shared_ptr<Alphabet> spAlphabet;
std::array<spAlphabet(*)(), Alphabet_Types::value> factories();
Here is how we define our (toy) letter classes:
struct A:Letter<A>{};
struct B:Letter<B>{};
ie, use Letter<> as a CRTP base instead of Alphabet.
The only thing left is to write the function factories.
Index boilerplate. C++1y has a replacement:
template<unsigned...>struct indexes{typedef indexes type;};
template<unsigned Max, unsigned... Is> struct make_indexes:make_indexes<Max-1,Max-1,Is...>{};
template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{};
The actual implementation via a helper function. We get a pack of indexes and expand it, building our std::array of function pointers from our shared_maker above instantiated with an indexed type from the Alphabet_Types we wrote above:
template<unsigned...Is>
std::array<spAlphabet(*)(), Alphabet_Types::value> factories(indexes<Is...>){
return {nth_apply_t<shared_maker,Is,Alphabet_Types>{}...};
}
The actual factories function just forwards to the above helper:
std::array<spAlphabet(*)(), Alphabet_Types::value> factories(){
return factories(make_indexes<Alphabet_Types::value>{});
}
And some trivial test code:
int main() {
std::vector<spAlphabet> vec;
auto builders = factories();
for (int i = 0; i < 2; ++i) {
vec.push_back(builders[i]());
}
for( auto&& ptr:vec ) {
std::cout << ptr->get_index() << "\n";
}
}

static if in plain c++?

Problem in short:
How could one implement static if functionality, proposed in c++11, in plain c++ ?
History and original problem:
Recently I came up with a problem like this. I need a class Sender with an interface like
class Sender
{
void sendMessage( ... );
void sendRequest( ... );
void sendFile( ... );
// lots of different send methods, not important actually
}
In some cases I will need to create a DoubleSender, i.e. an instance of this class, which would call its methods twice, i.e. when calling, let's say, a sendMessage(...) method, the same message has to be sent twice.
My solutions:
First approach:
Have an isDouble member, and in the end of each method call make a check
sendMessage(...) { ... if( isDouble ) { sendMessage( ... ); }
Well, I don't want this, because actually I will need double posting very recently, and this part of code in time-critical section will be 98% passive.
Second approach:
Inherit a class DoubleSender from Sender, and implement its methods like:
void DoubleSender::sendMessage( ... )
{
Sender::sendMessage(...);
Sender::sendMessage(...);
}
Well, this is acceptable, but takes much space of unpleasant code (really much, because there are lots of different send.. methods.
Third approach:
Imagine that I am using c++11 :). Then I can make this class generic and produce the necessary part of code according to tempalte argument using static if:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
static if ( T == Single )
{
sendMessage(...);
}
}
};
This is shorter, easier to read than previous solutions, does not generate additional code and... it's c++11, which I unfortunately cannot use in my work.
So, here is where I came to my question - how can I implement static if analog in c++ ? Also, I would appreciate any other suggestions about how to solve my original problem.
Thanks in advance.
Quoting #JohannesSchaubLitb
with my static_if that works on gcc one can do it :)
in some limited fashion
(see also here)
This trick involves a specific GCC interpretation of the specs on Lambdas in C++11. As such, it will (likely) become a defect report against the standard. This will lead to the trick no longer working in more recent version of GCC (it already doesn't work in 4.7).
See the comment thread below for some more details from Johanness
http://ideone.com/KytVv:
#include <iostream>
namespace detail {
template<bool C>
struct call_if { template<typename F> void operator<<(F) { } };
template<>
struct call_if<true> {
template<typename F>
void operator<<(F f) { f(); }
};
}
#define static_if(cond) detail::call_if<cond>() << [&]
template<bool C, typename T>
void f(T t) {
static_if(C) {
t.foo();
};
}
int main() {
f<false>(42);
}
Why not make the send implementation a policy of the sender class and use CRTP:
template<class Derived>
class SingleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
}
};
template< class Derived >
class DoubleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
static_cast<Derived *>(this)->f(...);
}
};
template< class SendPolicy>
class Sender : public SendPolicy< Sender >
{
public:
void sendMessage( ... )
{
// call the policy to do the sending, passing in a member function that
// acutally performs the action
callWrapperImpl( &Sender::sendMessageImpl, ... );
}
void doSomethingElse( ... )
{
callWrapperImpl( &Sender::doSomethingElseImpl, ... );
}
protected:
void sendMessageImpl(... )
{
// Do the sending here
}
void doSomethingElseImpl(... )
{
// Do the sending here
}
};
The public sendXXX functions in you class simply forward to the call wrapper, passing in a member function that implements the real functionality. This member function will be called according to the SendPolicy of the class. CRTP saves the use of bind to wrap the arguments and this pointer up with the member function to call.
With one function it doesn't really cut down on the amount of code, but if you have a lot of calls it could help.
Note: This code is a skeleton to provide a possible solution, it has not been compiled.
Note: Sender<DoubleSenderPolicy> and Sender<SingleSenderPolicy> are completely different types and do not share a dynamic inheritance relationship.
Most compilers do constant folding and dead code removal, so if you write a regular if statement like this:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
if ( T == Single )
{
sendMessage(...);
}
}
};
The if branch will get removed when the code is generated.
The need for static if is when the statements would cause a compiler error. So say you had something like this(its somewhat psuedo code):
static if (it == random_access_iterator)
{
it += n;
}
Since you can't call += on non-random access iterators, then the code would always fail to compile with a regular if statement, even with dead code removal. Because the compiler still will check the syntax for before removing the code. When using static if the compiler will skip checking the syntax if the condition is not true.
std::string a("hello world");
// bool a = true;
if(std::is_same<std::string, decltype(a)>::value) {
std::string &la = *(std::string*)&a;
std::cout << "std::string " << la.c_str() << std::endl;
} else {
bool &la = *(bool*)&a;
std::cout << "other type" << std::endl;
}