I'm new to metaprogramming, and I am having a const-related issue when using a tab with it.
Let's say we have several "types". Each of the types have different version, and we shall be able to handle all vesrion for each type. For that, we use a struct that contains standard info about the type, and an array containing info for each version.
The thing is, each type does not have the same number of versions. Also, the versions numbers are not very high, so I prefer not to use dynamic allocation of the said tables. But if I do static allocation, I need to have a table with the same size for each instance of the structure. That means, I have to get the highest version value and use it as the size of the array.
Here I come : I want to create a small metaprogramming template which gives the highest version value # compile time, so I can have a fixed size of the array that will surely contains the necerrasy info for each type. But I get a compile error.
Here is a simplified sample code that reproduce the issue (the error follows it)
#include <stdio.h>
// change values here
#define VERSION_ALPHA 3
#define VERSION_BETA 5
#define VERSION_GAMMA 2
// different available types
enum TYPES
{
T_ALPHA = 0,
T_BETA,
T_GAMMA,
T_COUNT, // number of types
};
// to access versions more easily from code
static const int typeVersions[T_COUNT] =
{
VERSION_ALPHA,
VERSION_BETA,
VERSION_GAMMA
};
// this meta is used to get the highest version values between all types
template<int i>
class HighestVersion
{
private:
// version of type -1
enum
{
PREVIOUS = HighestVersion<i-1>::VALUE
};
public:
// current max value
enum
{
VALUE = (typeVersions[i] > PREVIOUS ? typeVersions[i] : PREVIOUS)
};
};
// first version
template<>
class HighestVersion<0>
{
public:
// current max value
enum
{
VALUE = typeVersions[0]
};
};
// highest version macro
#define HIGHEST_VERSION HighestVersion<T_COUNT>::VALUE
// holds info about a single type
struct TypeInfo
{
char * s_pName; // name of the type as string
unsigned int s_Flags[HIGHEST_VERSION]; // flags for each available version of this type
};
int main()
{
// instanciate
TypeInfo infos[T_COUNT];
// do stuff, set name, load flags....
/*...*/
// for test purpose, print max version value (should print 5 in this situation)
printf("%d\n", HIGHEST_VERSION);
}
The compiler says :
error C2057: expected constant expression
# the lines
VALUE = (typeVersions[i] > PREVIOUS ? typeVersions[i] : PREVIOUS)
and
VALUE = typeVersions[0]
It seems that the compiler tells me that the table's contents are not constant. I assume it's because the table is interpreted as a pointer which is no constant in that case (so if the pointer changes the contents are not the same). Is there a way to correct that so I can use the script ? It will make the user to not need to manually set the size of that table...
Thanks in advance :)
I'm sure not it's even possible to make this work with a static array.
A possible alternative is a trait class:
template<TYPES>
struct typeVersions;
// specializations for each type
template<>
struct typeVersions<T_ALPHA> { static const int version = VERSION_ALPHA; };
template<>
struct typeVersions<T_BETA> { static const int version = VERSION_BETA; };
// etc...
You'd use it like this:
enum {
VALUE = typeVersions<i>::version
};
As jrok said, it is likely not possible to do this with a static array. But neither is it
necessary to create a trait-specialization for each type-version if you have an adequately
conforming C++11 compiler.
I see that you are using VC++ and you are probably committed to it, which regrettably means the only adequately conforming C++11 compiler you might have or lay your hands right now on is VC++ 2013 Preview. If you can use that then the simple variadic template solution illustrated by the following modification of your program will work for you:
#include <stdio.h>
// change values here
#define VERSION_ALPHA 3
#define VERSION_BETA 5
#define VERSION_GAMMA 2
// different available types
enum TYPES
{
T_ALPHA = 0,
T_BETA,
T_GAMMA,
T_COUNT, // number of types
};
template<int ...Versions>
struct versions_list
{
static_assert(sizeof ...(Versions),
"Cannot have 0 versions");
};
template<int Only>
struct versions_list<Only>
{
static const int max = Only;
};
template<int First, int Last>
struct versions_list<First,Last>
{
static const int max = First > Last ? First : Last;
};
template<int First, int Second, int ...Rest>
struct versions_list<First,Second,Rest...>
{
static const int tail_max = versions_list<Second,Rest...>::max;
static const int max = First > tail_max ? First : tail_max;
};
// Update your version list here:
typedef versions_list<VERSION_ALPHA, VERSION_BETA, VERSION_GAMMA> typeVersions;
#define HIGHEST_VERSION typeVersions::max
// holds info about a single type
struct TypeInfo
{
char * s_pName; // name of the type as string
unsigned int s_Flags[HIGHEST_VERSION]; // flags for each available version of this type
};
int main()
{
// instanciate
TypeInfo infos[T_COUNT];
// do stuff, set name, load flags....
/*...*/
// for test purpose, print max version value (should print 5 in this situation)
printf("%d\n", HIGHEST_VERSION);
}
The HIGHEST_VERSION macro is really pointless here: you could just delete its definition and replace all occurrences with typeVersions::max.
By the way, if you really want to use C's stdio API in a C++ program rather than the C++
iostream API, strictly you ought to use #include <cstdio>, not #include <stdio.h>
I am not sure if this can be done with C-style arrays, but if you have compiler support for C++11 then please check my solution:
#include <array>
#include <iostream>
template <int Size, int Indice>
struct HighestValue
{
static int get(std::array<int, Size> checkedArray) {
return std::max(HighestValue<Size, Indice - 1>::get(checkedArray), checkedArray[Indice]);
}
};
template <int Size>
struct HighestValue<Size, 0>
{
static int get(std::array<int, Size> checkedArray) {
return checkedArray[0];
}
};
template<size_t Size>
int checkMax(std::array<int, Size> checkedArray)
{
return HighestValue<Size, Size - 1>::get(checkedArray);
}
int main()
{
std::array<int, 7> test {1, 5, 2, 3, 123, 5, 2};
std::cout << checkMax(test);
}
Currently I do not have spare time to play with this, but I am sure it could be improved further.
Related
Suppose that I have a Foo class like this, and I need many instances of it.
class Foo {
public:
Pool* bars; // a global list of bars, each may have a different type
template<typename T>
T& AddBar(int x) {
return bars->emplace<T>(x);
}
template<typename T>
T& GetBar() {
return bars->get<T>(); // a very slow function
}
}
All the instances of Foo share the same pool of bars, which contains many bars of possibly different types. For example, bars may be a list of bars {A bar1, B bar2, A bar3, C bar4} where ABC are some class types, but each Foo foo instance can only have one bar of a specific type, e.g., a foo instance cannot have two bars of type A.
Given an instance Foo foo, I can get a specific type of bar using foo.GetBar<A>(), foo.GetBar<B>(), etc, but calling the bars->get<T>() function is slow and expensive. Therefore, I'm thinking of caching the result of GetBar() so that subsequent calls can return immediately without querying the pool again.
Now this is what I came up with: I created a static variable inside the member function to store the value of bar, it is only initialized and assigned value once.
template<typename T>
T& GetBar() {
static T bar {};
if (bar == T {}) {
bar = bars->get<T>(); // a very slow function
}
return bar;
}
The problem is that, using the static keyword, this variable is now shared across all instances of Foo. If I try to get a bar of type A from different instances, they would return the same result.
Foo foo1;
Foo foo2;
foo1.AddBar<A>(1);
foo2.AddBar<A>(2);
foo1.GetBar<A>(); // returns a bar (type = A, value = 1)
foo2.GetBar<A>(); // returns the same bar with value 1, not 2
How can I cache every bar of type T inside the class and prevent it from being shared by other instances? I don't know how to store generic types as member variables, besides, storing each type T of bar can be a huge mess.
Edit: I know it'd be much easier to cache the result outside the class, on the caller's side. I'm just curious if there's an elegant way of caching inside the class.
Edit2: bars is a pointer to a registry pool, whose type is a complicated data structure, not a raw list or array. To clarify, I'm using the EnTT library to integrate entity-component-system into my application, but not sure how the pool is maintained internally in details.
Edit3: if you wonder what ABCs are, conceptually, these types are not known at compile time. but need to be determined at runtime. In fact, they are just many other class types I implemented, so I can also hardcode them into the Foo class, in which case I probably should use the factory pattern along with a scripting language for automatic code generation, but that would beat the purpose of using generics in the first place.
While writing a mockup, with the idea of n. 1.8e9-where's-my-share m., for your "complicated registry pool" I wrote the actual could be implementation of Foo. I left in there Foo only to also give some suggestions. If you want so have more than one variable of one type you would have to change the value type of the map of course, like from std::any to std::vector<std::any>. Otherwise please clarify your question more.
#include <iostream>
#include <string>
#include <map>
#include <any>
struct Pool {
template<typename T>
void emplace(T x) {
this->elements_.insert_or_assign(typeid(T).hash_code(), std::make_any<T>(x));
}
template<typename T>
T& get() {
return std::any_cast<T&>(elements_.at(typeid(T).hash_code()));
}
private:
std::map<std::size_t, std::any> elements_;
};
class Foo {
public:
Foo(Pool& pool): bars_(pool) {}
void AddBar(int x) {
return bars_.emplace<int>(x);
}
template<typename T>
T& GetBar() {
return bars_.get<T>(); // a very slow function
}
private:
Pool& bars_;
};
int main(){
Pool pool;
pool.emplace(4.3); pool.emplace(std::string("a value"));
Foo foo1(pool);
foo1.AddBar(3);
std::cout << foo1.GetBar<int>() << "\n";
}
All ECS implementations abandon static type safety somewhere deep under their hood, although they can hide the ugly casts from the user or use the likes of std::any as in the other nice answer.
That said, here's an alternative way to approach it (simplified but it should give you the right idea) which avoids map lookups except once on calling the get function for a new type, T:
#include <iostream>
#include <unordered_map>
#include <typeinfo>
#include <any>
class Foo
{
public:
template <class T>
T& get()
{
// Fetch a unique index for T to use for our std::vector.
const std::size_t n = type_index<T>();
// Resize if it's a new type we're encountering.
if (n >= bars.size())
bars.resize(n+1);
// Emplace if it's a former type of bar that's new for this instance
// of Foo.
if (!bars[n].has_value())
bars[n].emplace<T>();
// Returns the bar for that index cast to T&.
return std::any_cast<T&>(bars[n]);
}
private:
// Stores all the elements.
std::vector<std::any> bars;
// Returns a unique type index for T.
template <class T>
static std::size_t type_index()
{
// Using static here avoids repeat lookups into the hash map.
static const std::size_t n = lookup_type_index<T>();
return n;
}
// Looks up a unique type index for T.
template <class T>
static std::size_t lookup_type_index()
{
// Warning: hash_code is not guaranteed to be unique for all
// types in all compilers (two different types could return
// the same hash code, e.g.). I recommend using something else but
// that gets a bit involved (can expand and show you how if
// needed). Also consider a lock here for thread safety.
std::size_t key = typeid(T).hash_code();
auto it = idxs.find(key);
if (it != idxs.end())
return it->second;
idxs[key] = counter;
return counter++;
}
static inline std::unordered_map<std::size_t, std::size_t> idxs;
static inline std::size_t counter = 0;
};
int main()
{
using namespace std;
Foo f, f2;
f.get<int>() = 123;
f.get<double>() = 1.23;
f2.get<int>() = 456;
f2.get<double>() = 4.56;
cout << f.get<int>() << endl; // --> 123
cout << f.get<double>() << endl; // --> 1.23
cout << f2.get<int>() << endl; // --> 456
cout << f2.get<double>() << endl; // --> 4.56
}
I didn't bother to test it but it should give you the gist of the idea. Update: I bothered to test it and updated it with a hasty program you can run after discovering some typos just double-checking what I wrote and realizing I ought to at least try to compile what I write. To avoid constantly looking into a type map, we map types to an index into a vector. You can extend that with sub-indices and so forth as your original example suggests. The above illustrates the main idea.
Please note the warning in the code above about std::type_info::hash_code as it applies to both mine and the other answer. I can offer a safe and portable alternative and one that doesn't even require RTTI but that gets a bit involved. You can usually find a bunch of examples out there if you search for ways to portably map a type T to an integer at compile-time that you can use at runtime.
I have tried to create a compile-time simple Key-Value map in C++. I'm compiling with /std:c++11.
(Using IAR compiler for embedded code and only cpp++11 is supported at the moment)
I've learnt a little bit about meta-programming.
I don't want my map to have a default value, if key is not found,
like this post: How to build a compile-time key/value store?
I want to get compiler error, if in my code I'm trying to get a value which is not stored in the map.
Here is what I've done:
#include <iostream>
template <int kk, int vv>
struct KeyValue
{
static const int k = kk, v = vv;
};
// Declaration
template <typename kv, typename...>
struct CompileTimeMap;
// Recursive Definition
template<typename kv, typename... rest>
struct CompileTimeMap<kv, rest...>
{
template<int k_input>
struct get
{
static const int val = (k_input == kv::k) ? kv::v : CompileTimeMap<rest...>::get<k_input>::val;
};
};
// Base Definition
template <typename kv>
struct CompileTimeMap<kv>
{
template<int k_input>
struct get
{
static const int val = (k_input == kv::k) ? kv::v;
};
};
// ----------------------------- Main -----------------------------
typedef CompileTimeMap<KeyValue<10, 20>, KeyValue<11, 21>, KeyValue<23, 7>> mymap;
int main()
{
// This calles should be ok !! :)
std::cout << mymap::get<10>::val << std::endl;
std::cout << mymap::get<11>::val << std::endl;
std::cout << mymap::get<23>::val << std::endl;
// This line should resolve a compile error !! (there is no key of 33)
std::cout << mymap::get<33>::val << std::endl;
}
I get the following error: error C2131: expression did not evaluate to a constant.
How can I make this work? Many thanks :)
Don't write a template metaprogram, where it is not necessary. Try this simple solution (CTMap stands for compile time map):
template <class Key, class Value, int N>
class CTMap {
public:
struct KV {
Key key;
Value value;
};
constexpr Value operator[] (Key key) const
{
return Get (key);
}
private:
constexpr Value Get (Key key, int i = 0) const
{
return i == N ?
KeyNotFound () :
pairs[i].key == key ? pairs[i].value : Get (key, i + 1);
}
static Value KeyNotFound () // not constexpr
{
return {};
}
public:
KV pairs[N];
};
constexpr CTMap<int, int, 3> ctMap {{ { 10, 20 }, { 11, 21 }, { 23, 7 } }};
static_assert (ctMap[10] == 20, "Error.");
static_assert (ctMap[11] == 21, "Error.");
static_assert (ctMap[23] == 7, "Error.");
// constexpr auto compilationError = ctMap[404];
You will get a compilation error, if you uncomment the last line (live demo). The compiler will direct you to the KeyNotFound () : line, from
which the reason of the failure should be obvious.
Remarks
The member variable pairs is made public, to make it possible to initialize the map with list-initialization.
The given N and the number of pairs that initialize CTMap should match. If N is less, you get a compilation error. If N is greater, zero-initialized pairs ({ 0, 0 }) will be silently added to pairs. Pay attention to this.
The (compiler generated) constructor does not check for duplicate keys. operator[] will find the first, but the intended usage is that you do not initialize CTMap with duplicate keys.
Recursion is not necessary in C++14. We can write a for loop in a constexpr function (live demo). The linked implementation gives another idea for giving a compiler error in case the key is not found: an exception is thrown. The member variable pairs is made private.
Intended to be used in compile time
This is a linear map, and parameters are passed by value. My intention was that the map will be used in compile time evaluated code, where this should not be a problem.
Note also that when evaluated in run time, this class won't give any feedback if the key is not found in the map.
Let's take a closer look of how ctMap[10] works in different situations. I have tried the following with three compilers (MSVC v19.24, clang 10.0.0, gcc 9.3).
constexpr int C = ctMap[10]; – The global constant C will be initialized with 20 even in debug builds. No computation is made during run-time. Note that to ensure, that the global will be created, you have to take its address somewhere. If you use the value of C, its value (20) will be substituted where it is used, and C won't be created in the object file even in debug builds.
int Foo () { return ctMap[10]; } – In debug builds operator[] will be called. In release builds MSVC inlines operator[] to Foo, i.e. eliminates one call, but the resulting code has linear complexity (the compiler is not forced to do the computation in compile time, and code optimization is poor in MSVC). Clang and gcc compiles a return 20;.
And this is how ctMap[404] works (with the same three compilers):
constexpr int C = ctMap[404]; – Does not compile, as mentioned above.
int Foo () { return ctMap[404]; } – The same remarks apply as for ctMap[10], but Foo will return 0. You cannot know, that 404 was not in the map. To get the compilation error, Foo has to be constexpr and forced to be evaluated in compile time by e.g. assigning it to a constexpr variable or an enumerator, using it in a template argument, as a size of a C array, in a static_assert, etc.
Here's my issue, I would like to call the getters/setters of one of my objects, but not directly, I want to do it by using a std::string.
I found this but it won't work on my case I think it is because my function aren't defined in my main method but in my square class. Also my function are not all defined the same way there's void(std::string) std::string() void(int)...
here's an exemple of what a would like to do.
my object square
#include <map>
#include <functional>
#include <string>
class Square{
private:
std::string name;
int width;
float happinessPoint; //extremly important for your square.
public:
void setName(std::string);
void setWidth(int);
void setHappinessPoint(float);
std::string getName()
int getWidth()
float getHappinnessPoint()
}
and my main
#include "Square.h/cpp"
int main(){
Square square = Square("Roger",2,3.5);
// here in my magicalFunction I ask to the users the new values for my square (all in std::string for now)
vector <std::string> newValueForSquare = magicalFunction();
for (unsigned int i=0; i < newValueForSquare.size(), i++){
//here I have a function which tell me if my std::string
// is in fact a float or an int
// and I would like to call each of my setters one by one to
// sets my Square to some value I asked to the user before all that.
// something like that:
// someFunction("setName","Henry")
}
}
I hope i have been clear it's pretty hard to explain something you don't know how to do. If you want me to be more specific tell me and I'll do what I can.
EDIT: What I want to do is to call for example my square.setName() with a str::string without writting this square.setName in my main.
To call functions, based on a string, you have some choices. Before I list the choices, please search the internet for "C++ factory design pattern".
If-else ladder
Lookup table
Map / Associative array
Hash table
There may be other methods, but the above come to mind.
if-else ladder (a.k.a. switch)
The problem with this method is that the switch statement doesn't work with strings nor text literals. So you'll have to suffice with if statements:
if (string == "Roger")
{
Process_Roger();
}
else if (string == "Felicity")
{
Process_Felicity();
}
else
{
Display_Error_Message();
}
Anytime you need to add a new string, you will have to add another "else if" statement to the ladder. Not only do you have to change the code, but you also have to retest it.
Lookup Table
You will need to understand function pointers for this technique and the map technique. Consider this a prerequisite.
Use a structure for mapping text strings to function pointers:
struct Text_Function_Pointer
{
const char * name;
Function_Pointer p_function;
};
static const Text_Function_Pointer table[] =
{
{"Larry", Process_Larry},
{"Felicity", Process_Felicity},
};
static const unsigned int table_size =
sizeof(table) / sizeof(table[0]);
//...
for (unsigned int i = 0; i < table_size; ++i)
{
if (search_name == table[i].name)
{
// Execute the processing function.
table[i].p_function(search_name);
break;
}
}
An issue with this technique is that all the function pointers must have the same signature. This is true for the map as well.
A nice feature is that the data in the table is constant, so it can be placed in Read-Only Memory.
Also, to add more associations, add an entry to the the table. The search / processing function hasn't changed, so it doesn't need to be tested again.
Map / Associative Array
Prerequisite: Function pointers.
Declare a std::map<std::string, Function_Pointer_Type>. Add your names and functions to the map:
std::map<std::string, Function_Pointer_Type> dispatch_table;
dispatch_table["Roger"] = Process_Roger;
dispatch_table["Felicity"] = Process_Felicity;
dispatch_table["Larry"] = Process_Larry;
//...
// Execute appropriate processing function:
(dispatch_table[search_name])();
One issue with this method is that the std::map data structure needs to be initialized; it can't be directly accessed or loaded from executable code.
Again, all functions must have the same signature.
Hash Table
The idea here is to have an array of function pointers or an array of structures with text & function pointers. Create a hash function that generates a unique array index based on the name string. Use the index to get the function pointer from the array, then execute the function via the function pointer.
Several solutions are available to you. You basically want to parse user input to fill your Square class attribute.
One way is to use the std::stoi family of functions:
std::vector<string> values { "Roger", "2", "3.5" };
std::string name = values[0]; // No problem, two strings
int width = std::stoi(values[1]); // stoi = stringToInt
float happiness = std::stof(values[2]); // stof = stringToFloat
I'm not sure why you'd need the for loop, unless there is something I didn't understand in your question. I'll update my answer accordingly.
Update 1
After reading other answers, I would like to propose my solution to your problem. As stated several times in my comments, this is not an easy answer !
I needed such a class to write a generic test engine, and this is the code I used. It works really well with any type of function (except for routines with a return type of void -- a simple template specialization would solve it though)
# include <functional>
# include <tuple>
template<int ...>
struct seq
{
};
template<int N, int ...S>
struct gens : gens<N - 1, N - 1, S...>
{
};
template<int ...S>
struct gens<0, S...>
{
typedef seq<S...> type;
};
struct callable_base
{
virtual void operator()() = 0;
virtual ~callable_base()
{ }
};
class Task
{
private:
template<class RT, class Functor, class ...Args>
struct functor : public callable_base
{
functor(RT& result, Functor func, Args ...args)
: _ret(result)
{
_func = func;
_args = std::make_tuple(args...);
}
void operator()()
{
_ret = call(typename gens<sizeof...(Args)>::type());
}
template<int ...S>
RT call(seq<S...>)
{
return (_func(std::get<S>(_args)...));
}
private:
std::function<RT(Args...)> _func;
std::tuple<Args...> _args;
RT& _ret;
};
public:
Task()
{
_functor = nullptr;
}
template<class RT, class Functor, class ...Args>
Task(RT& result, Functor func, Args... args)
{
_functor = new functor<RT, Functor, Args...>(result, func, args...);
}
void operator()()
{
(*_functor)();
}
~Task()
{
delete _functor;
}
private:
callable_base *_functor;
};
The idea behind this code is to hide the function signature in the inner class Task::functor and get the return value in the first parameter passed to the Task(...) constructor. I'm giving this code first because I think it might help some people, but also because I think it is an elegant solution to your problem. Bear in mind that to understand most of the code, you need solid C++ knowledge. I'll detail the code in subsequent updates if needed.
Here's how you'd use it:
int main()
{
int retVal;
std::string newName;
std::map<std::string, Task *> tasks {
{"setName", new Task(retVal, &Square::setName, &newName)}
...
}
/* Modify the name however you want */
...
tasks["setname"]();
}
This whole class could be optimized, of course, primarily thanks to C++14 and move semantics, universal references and all, but I kept it simple ~
A major problem is that you have to use pointers if you don't know the values of the parameters at the time you fill the task map. I'm working on another version to simplify this aspect, but I wanted to show you that C++ is not designed to do what you ask simply. Maybe you come from a functional or JS world, in which this would be trivial x)
Update 2
I just wanted to point out that with C++14, you could omit the first 3 structures that are here to help me expand my tuple in an argument list using interger_sequence
I did two classes, The first is template class Bit<size> that convert decimal number to a binary. The second is LogicalExpression class.
Bit class:
template<int size>
class Bit
{
public:
Bit(int);
void ConvertToBinary(int);
bool number[size];
int bit;
};
template <int size> Bit<size>::Bit(int decimalNumber)
{
this->bit = 0;
ConvertToBinary(decimalNumber);
}
template <int size> void Bit<size>::ConvertToBinary(int decimalNumber)
{
number[size - ++this->bit] = decimalNumber % 2;
if (size != this->bit) {
ConvertToBinary(decimalNumber / 2);
}
}
LogicalExpression class:
#include "Bit.h"
class LogicalExpression
{
private:
char* expression;
char* variables;
int expLenght;
int varLenght;
public:
LogicalExpression(char*);
~LogicalExpression();
bool ExpressionToBoolean(char*, Bit<????>); //here is the problem
I want to use the LogicalExpression class as a normal non-template class, as a result I do not know how to declare const argument for Bit<???>, it should be Bit<varLenght>, but varLenght is non-const value and i do not want to do LogicalExpression<varLenght> obj .
Hope that my English not so bad, for not understanding me.
The problem here is possibly a misunderstanding of how templates work.
Templates are evaluated at compile time. Therefore the value inbetween < > can not contain a non-const. Its simply not possible because templates are not evaluated at run time. This is actually a strength, not a weakness (see TMP). For comparison they are more like pre-processor defines then say a function call but they are actually not the same thing as macros
In this case you need to rethink your design. in this part:
template<int size>
class Bit
{
public:
Bit(int);
void ConvertToBinary(int);
bool number[size];
int bit;
};
You either want "number" to be a dynamic array so that it would either become something like:
class Bit
{
public:
Bit(int length){ number = new bool[length]; } ;
~Bit(){delete number;}
void ConvertToBinary(int);
bool* number;
int bit;
};
it doesn't need to be a template and would be used like:
bool ExpressionToBoolean(char*)
{
Bit foo(varLength);
}
You could use std::vector for simplicity.
OR "LogicalExpression" should be a template class (which you have said you don't want)
template<int varLenght>
class LogicalExpression
{
private:
char* expression;
char* variables;
int expLenght;
public:
LogicalExpression(char*);
~LogicalExpression();
bool ExpressionToBoolean(char*, Bit<varLenght>); //here is the problem
But really this boils down to a question of where you want your memory allocated, do you want it on the heap or the stack?
Heap : Dynamic array (can be evaluated at run time)
stack : Templates (can not be evaluated at run time)
If you don't care, i would probably just stick with the dynamic array approach because you could easily over complicate the problem with templates...but this problem may be suited to TMP based on your requirements. If you want it on stack then you will have to use some form of
LogicalExpression< "const" > obj
"somewhere", which if its a syntactical taste you could use something like:
typedef LogicalExpresion8Bit LogicalExpression<8>
If you want dynamic evaluation then you have to either use dynamic memory or something a bit crazier like a combination of polymorphic and interfaces which will most likely lead to more memory on the stack then you actually want/need, not to mention a lot more code...(i.e. each variant stored in an array and selected via index).
Consider the following code
#include <iostream>
enum MyEnum{
A,
B,
END
};
template <int N>
class Trait {};
template<>
class Trait<A> {
public:
static int funct(int i) {return i*3;}
};
template<>
class Trait<B> {
public:
static int funct(int i) {return i*24;}
};
using namespace std;
int main(){
int i = 1;
switch(i){
case A: cout << Trait<A>::funct(i) << endl; break;
case B: cout << Trait<B>::funct(i) << endl; break;
}
}
Which will print 24 on the screen.
Assume now that I have many more values in the enum and that I define all the corresponding
template specializations of the class Trait.
To avoid writing all the code necessary in the switch statement I wrote a REPEAT macro which works almost like I want:
#include <iostream>
#define REPEAT(N, macro) REPEAT_##N(macro)
#define REPEAT_0(macro)
#define REPEAT_1(macro) REPEAT_0(macro) macro(0)
#define REPEAT_2(macro) REPEAT_1(macro) macro(1)
#define REPEAT_3(macro) REPEAT_2(macro) macro(2)
#define REPEAT_4(macro) REPEAT_3(macro) macro(3)
// etc...
// enum and class definitions
int main(){
#define MY_MACRO(N) case N: cout << Trait<N>::funct(i) << endl; break;
switch(i){
REPEAT(2, MY_MACRO)
}
}
The problem I have with this approach is that I cannot use
REPEAT(END, MY_MACRO)
because the preprocessor doesn't know about my enum.
Question: Is there a way to generate automatically the switch statement?
Notes:
The situation where I have to use this is much more complicated and having something automated would be really helpful.
It is important for me to use a switch statement because of the speed which can be achieved (speed is crucial for my application).
Thanks!
EDIT 1
More notes:
It is important that the generation of the switch depends on the value of END defined in the enum.
EDIT 2/3
I decided to make an addition here to explain better my application and why I prefer some solutions to others
In my real application the enum contains almost 50 different values and it will be extended in the future (hopefully by other people). The enum contains consecutive values.
the class "Trait" has more than 1 member function (currently 5). Furthermore, I need to use all this in 5 different files. If I don't use an automated way of generating what I need I end up writing many times code which is basically the same.
the member functions of Trait are used in the same way all the times.
currently, inside my switch I have a function call which looks like this (in1, in2 and out are all double passed by reference, const for the first two cases).
case A: Trait::funct(in1, in2, out); break;
Why do I like templates?
Consider the case Trait has 2 functions funct1 and funct2. I could define
template <int N>
class Trait {
public:
static int funct1(int i){static_assert(N!=N, "You forgot to define funct1");}
static int funct2(int i){static_assert(N!=N, "You forgot to define funct2");}
};
Now, if a function definition is missing, the compiler will return a meaningful error. When other people will make additions this will be helpful.
Using the method based on C++11 features suggested by Jarod42 I can avoid maintaining long arrays of function pointers which would be error prone.
Speed tests
So far I experimented with 3 solutions but with only two member functions in Trait:
the solution suggested by Jarod42
a simple array of function pointers as suggested by nndru and Ali
switch statement with the RETURN macro
The first two solutions seem to be equivalent, while the one based on the switch is 5 times faster. I used gcc version 4.6.3 with the flag -O3.
As you say, your enum is contiguous. In that case you don't need any templates or std::map or switch:
Use simply an array of function pointers and the enum as the index into the function pointer array!
#include <cassert>
#include <cstdio>
enum {
A,
B,
SIZE
};
int A_funct(int i) { return 3*i; }
int B_funct(int i) { return 24*i; }
typedef int (*enum_funct)(int );
enum_funct map[] = { A_funct, B_funct };
// In C++11 use this:
//static_assert( sizeof(map)/sizeof(map[0])==SIZE , "Some enum is missing its function!");
int main() {
assert(sizeof(map)/sizeof(map[0])==SIZE && "Some enum is missing its function!");
int i = 1;
std::printf("case A prints %d\n", map[A](i) );
std::printf("case B prints %d\n", map[B](i) );
}
UPDATE: From your comments:
My only concern about maintainability is about writing down explicitly
5 different function pointer arrays (if I don't automate this).
OK, now I understand the maintenance concern.
I believe you can only achieve this (no matter whether you use function pointer arrays or the switch approach) if you use some sort of source code generation, either with macros or write your own source code generator. You also have to work out some naming conventions so that the function pointer arrays (or the code at the case statements in the switch approach) can be automatically generated.
Since you didn't specify it, I just made up my own naming convention. If you are comfortable with macros, here is what I hacked together with the Boost Preprocessor Library by some mindless editing of the example:
#include <boost/preprocessor/repetition.hpp>
#define ENUM_SIZE 2
#define ENUM(z, n, unused) e##n,
enum {
BOOST_PP_REPEAT(ENUM_SIZE, ENUM, ~)
SIZE
};
#undef ENUM
int fA_e0(int i) { return 3*i; }
int fA_e1(int i) { return 24*i; }
int fB_e0(int i) { return 32*i; }
int fB_e1(int i) { return 8*i; }
typedef int (*enum_funct)(int );
#define MAP(z, n, case) f ## ##case ## _e##n,
enum_funct map_A[] = {
BOOST_PP_REPEAT(ENUM_SIZE, MAP, A)
};
enum_funct map_B[] = {
BOOST_PP_REPEAT(ENUM_SIZE, MAP, B)
};
#undef MAP
Here is what we get after the preprocessor resolved these macros (g++ -E myfile.cpp):
enum { e0, e1, SIZE };
[...]
typedef int (*enum_funct)(int );
enum_funct map_A[] = {
fA_e0, fA_e1,
};
enum_funct map_B[] = {
fB_e0, fB_e1,
};
So, as you can see, if you specify your own naming conventions, you can automatically generate the maps (function pointer arrays). The documentation is good.
However, if I were you, I would write my own source code generator. I would specify a simple text file format (key - value pairs on one line, separated by white space) and write my own tool to generate the desired C++ source files from this simple text file. The build system would then invoke my source code generator tool in the pre-build step. In that way, you don't have to mess with macros. (By the way, I wrote a little testing framework for myself and to circumvent the lack of reflection in C++ I use my own source code generator. Really not that difficult.)
The first two solutions seem to be equivalent, while the one based on
the switch is 5 times faster. I used gcc version 4.6.3 with the flag
-O3.
I would have to see your source code, the generated assembly and how you measured the time in order to understand how that happened.
So I also did my own speed tests. Since it would clutter this answer, the source codes are here: switch approach and the function pointer array approach.
As I expected: the switch approach is faster but only if you have a handful of branches. Andrei Alexandrescu also says the same in his talk
Writing Quick Code in C++, Quickly, at around 38 min. On my machine, the switch approach is as fast as the function pointer array approach if the enum size is 5. If the enum size is bigger than 5, the function pointer array approach is consistently faster. If the enum size is 200 and there are 10^8 function invocations, it is more than 10% faster on my machine. (The online codes have only 10^7 function invocations otherwise it times out.)
(I used link time optimization (-O3 -flto flag both to the compiler and the linker) and I can only recommend it; it gives a nice performance boost (in my codes up to 2.5x) and the only thing you need to do is to pass one extra flag. However, in your case the code was so simple that it didn't change anything. If you wish to try it: The link time optimization is either not available or only experimental in gcc 4.6.3.)
From your comments:
I made new experiments following step by step your benchmark method
but I still get better results with the switch statement (when the
enum size is 150 the switch is still almost twice as fast as than the
solution with pointers). [...]
In the test with my code the switch method performs always better. I run also some
experiments with your code and I got the same kind of results you got.
I have looked at the generated assembly codes, having at least 5 functions (5 cases). If we have at least this many functions, roughly speaking, what happens is that the compiler turns the switch approach into the function pointer approach with one significant disadvantage. Even in the best case, the switch always goes through 1 extra branch (integer comparison potentially followed by a jump) compared to the hand-coded function pointer array approach when dispatching to the function to be called. This extra branch belongs to the default: label which is generated even if you deliberately omit it in the C++ code; there is no way to stop the compiler from generating the code for this. (If you have at most 4 cases and all 4 function calls can be inlined, then it is different; however you already have 50 cases so it doesn't matter.)
Apart from that, with the switch approach, additional (redundant) instructions and paddings are generated, corresponding to the code at the case: labels. This potentially increases your cache misses. So, as I see it, the the switch is always inferior to the function pointer approach if you have more than a handful of cases (5 cases on my machine). That is what Andrei Alexandrescu says in his talk too; he gives a limit of ~7 cases.
As for the reasons why your speedtests indicate the opposite: These sort of speed testings are always unreliable because they are extremely sensitive to alignment and caching. Nevertheless, in my primitive tests, the switch approach was always slightly worse than the function pointer array, which is in agreement with my above analysis of the assembly codes.
Another advantage of the function pointer arrays is that it can be built and changed at runtime; this is something that you don't get with the switch approach.
The weird thing is that the speed I get with the function pointer
array changes depending on the enum size (I would expect it to be
roughly constant).
As the enum size grows, you have more functions and the instruction cache misses are more likely to happen. In other words, the program should run slightly slower if you have more functions. (It does on my machine.) Of course the whole thing happens at random, so there will be significant deviations, don't be surprised if it runs faster for ENUM_SIZE=42 than for 41. And as mentioned earlier, alignment adds additional noise to this.
In C++11, you may do the following:
#if 1 // Not in C++11
#include <cstdint>
template <std::size_t ...> struct index_sequence {};
template <std::size_t I, std::size_t ...Is>
struct make_index_sequence : make_index_sequence < I - 1, I - 1, Is... > {};
template <std::size_t ... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
#endif
namespace detail {
template <std::size_t ... Is>
int funct(MyEnum e, int i, index_sequence<Is...>)
{
// create an array of pointer on function and call the correct one.
return std::array<int(*)(int), sizeof...(Is)>{{&Trait<MyEnum(Is)>::funct...}}[(int)e](i);
}
} // namespace detail
int funct(MyEnum e, std::size_t i)
{
return detail::funct(e, i, make_index_sequence<std::size_t(END)>());
}
Note: enum should not have hole (so here A=0 and B=1 is ok)
Following macro may help:
#define DYN_DISPATCH(TRAIT, NAME, SIGNATURE, ENUM, ENUM_END) \
namespace detail { \
template <std::size_t ... Is> \
constexpr auto NAME(ENUM e, index_sequence<Is...>) -> SIGNATURE \
{ \
return std::array<SIGNATURE, sizeof...(Is)>{{&TRAIT<ENUM(Is)>::NAME...}}[(int)e]; \
} \
} /*namespace detail */ \
template <typename...Ts> \
auto NAME(ENUM e, Ts&&...ts) \
-> decltype(std::declval<SIGNATURE>()(std::declval<Ts>()...)) \
{ \
return detail::NAME(e, make_index_sequence<std::size_t(ENUM_END)>())(std::forward<Ts>(ts)...); \
}
And then use it as:
DYN_DISPATCH(Trait, funct, int(*)(int), MyEnum, END)
// now `int funct(MyEnum, int)` can be call.
You don't need templates at all to do this. More like good old X macros
#define MY_ENUM_LIST VAL(A) VAL(B)
// define an enum
#define VAL(x) x,
enum MyEnum { MY_ENUM_LIST END };
#undef VAL
// define a few functions doing a switch on Enum values
void do_something_with_Enum (MyEnum value, int i)
{
switch (value)
{
#define VAL(N) case N: std::cout << Trait<N>::funct(i) << std::endl; break;
MY_ENUM_LIST
#undef VAL
}
}
int do_something_else_with_Enum (MyEnum value)
{
switch (value)
{
#define VAL(x) case x: yet_another_template_mayhem(x);
MY_ENUM_LIST
#undef VAL
}
}
I've wasted enough time with this already. If you think templates are the solution, simply change your question to "templates experts only, preprocessor not good enough" or something.
You will not be the first wasting your time on useless templates. Many people make a fat living on providing bloated, useless solutions to inexisting problems.
Besides, your assumption of a switch being faster than an array of function pointers is highly debatable. It all depends on the number of values in your enum and the variability of the code inside your case statements.
Now if optimization is not such a big issue, you can simply use virtual methods to specialize the behaviour of whatever objects are selected by your enum and let the compiler handle the whole "automatic switch" stuff for you.
The only benefit of this approach is to avoid duplicating code if your objects are similar enough to make you think you will do a better job than the compiler handling them in a specialized way.
What you seem to be asking for is a generic solution for optimizing an unknown code pattern, and that is a contradiction in terms.
EDIT: thanks to Jarod42 for cleaning up the example.
It looks like you would like to associate and integer id with each function and find functions by the id.
If your id's are sequential you can have an array of function pointers indexed by that id, which would give you O(1) lookup complexity, e.g.:
typedef int Fn(int);
enum FnId {
A,
B,
FNID_COUNT
};
int fn_a(int);
int fn_b(int);
Fn* const fns[FNID_COUNT] = {
fn_a,
fn_b
};
int main() {
fns[A](1); // invoke function with id A.
}
If the id's are not sequential, you can still have a sorted array of {id, function_ptr} tuples and do binary search on it, O(lg(N)) lookup complexity.
None of these require macros or templates.
For numeric (database) type identifiers I have a template holding the identifiers. A dispatch via variadic templates calls a functor with the matching type traits:
#include <iostream>
#include <stdexcept>
// Library
// =======
class TypeIdentifier
{
public:
typedef unsigned Integer;
enum Value
{
Unknown,
Bool,
Int8,
UInt8,
Int16,
UInt16,
Int32,
UInt32,
Int64,
UInt64,
Float,
Double,
String,
LargeObject,
Date,
Time,
DateTime
};
template <Value ...Ids> struct ListType {};
typedef ListType<
Bool,
Int8,
UInt8,
Int16,
UInt16,
Int32,
UInt32,
Int64,
UInt64,
Float,
Double,
String,
LargeObject,
Date,
DateTime,
// Always the last value:
Unknown
>
List;
public:
TypeIdentifier(Integer value = Unknown)
: m_id(value)
{}
Integer id() const { return m_id; }
/// Involve a functor having a member function 'Result apply<Traits>()'.
template<typename Functor>
typename Functor::result_type dispatch(const Functor&);
private:
Integer m_id;
};
template<TypeIdentifier::Value I>
struct TypeTraits
{
static constexpr TypeIdentifier::Value Id = I;
static constexpr bool is(TypeIdentifier::Integer id) { return (Id == id); }
static bool is(TypeIdentifier type_identifier) { return (Id == type_identifier.id()); }
// And conversion functions
};
namespace TypeIdentifierDispatch {
template <typename Functor, TypeIdentifier::Value I, TypeIdentifier::Value ... Ids> struct Evaluate;
template <typename Functor>
struct Evaluate<Functor, TypeIdentifier::Unknown> {
static typename Functor::result_type
apply(TypeIdentifier::Integer id, const Functor&) {
throw std::logic_error("Unknown Type");
}
};
template <typename Functor, TypeIdentifier::Value I, TypeIdentifier::Value ... Ids>
struct Evaluate {
static typename Functor::result_type
apply(TypeIdentifier::Integer id, const Functor& functor) {
if(TypeTraits<I>::is(id))
return functor.template apply<TypeTraits<I>>();
else return Evaluate<Functor, Ids...>::apply(id, functor);
}
};
template <typename Functor, TypeIdentifier::Value ... Ids>
inline typename Functor::result_type
evaluate(TypeIdentifier::Integer id, const Functor& functor, TypeIdentifier::ListType<Ids...>)
{
return Evaluate<Functor, Ids...>::apply(id, functor);
}
} // namespace TypeIdentifierDispatch
template<typename Functor>
inline
typename Functor::result_type TypeIdentifier::dispatch(const Functor& functor) {
return TypeIdentifierDispatch::evaluate(id(), functor, TypeIdentifier::List());
}
// Usage
// =====
struct Print {
typedef void result_type;
template <typename Traits>
result_type apply() const {
std::cout << "Type Identifier: " << Traits::Id << '\n';
}
};
inline void print_identifier(unsigned value) {
TypeIdentifier(value).dispatch(Print());
}
int main ()
{
print_identifier(TypeIdentifier::String);
return 0;
}
Adding a new type to the library requires adjusting TypeIdentfier and (maybe) adding a specialized TypeTraits.
Note the enum values can be arbitrary.
Using recursive template you can automatically generate construction equivalent to
if (i = A)
Trait<A>::funct(i);
else if (i = B)
Trait<B>::funct(i);
I think it performance is similar to switch statement. Your original example can be rewritten as below.
#include <iostream>
using namespace std;
enum MyEnum {
A,
B,
END
};
template <MyEnum N>
class Trait
{ public:
static int funct(int i)
{
cout << "You forgot to define funct" << i;
return i;
}
};
template<>
class Trait<A> {
public:
static int funct(int i) { return i * 3; }
};
template<>
class Trait<B> {
public:
static int funct(int i) { return i * 24; }
};
template <MyEnum idx>
int Switch(const MyEnum p, const int n)
{
return (p == idx) ? Trait<idx>::funct(n) : Switch<(MyEnum)(idx - 1)>(p, n);
}
template <>
int Switch<(MyEnum)(0)>(const MyEnum p, const int n)
{
return Trait<(MyEnum)(0)>::funct(n);
}
int funct(MyEnum n)
{
return Switch<END>(n, n);
}
int main() {
MyEnum i = B;
cout << funct(i);
}