How do I declare non-const argumets to an object template - c++

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).

Related

How to call a function from an object with a std::string

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

C++ function argument safety

In a function that takes several arguments of the same type, how can we guarantee that the caller doesn't mess up the ordering?
For example
void allocate_things(int num_buffers, int pages_per_buffer, int default_value ...
and later
// uhmm.. lets see which was which uhh..
allocate_things(40,22,80,...
A typical solution is to put the parameters in a structure, with named fields.
AllocateParams p;
p.num_buffers = 1;
p.pages_per_buffer = 10;
p.default_value = 93;
allocate_things(p);
You don't have to use fields, of course. You can use member functions or whatever you like.
If you have a C++11 compiler, you could use user-defined literals in combination with user-defined types. Here is a naive approach:
struct num_buffers_t {
constexpr num_buffers_t(int n) : n(n) {} // constexpr constructor requires C++14
int n;
};
struct pages_per_buffer_t {
constexpr pages_per_buffer_t(int n) : n(n) {}
int n;
};
constexpr num_buffers_t operator"" _buffers(unsigned long long int n) {
return num_buffers_t(n);
}
constexpr pages_per_buffer_t operator"" _pages_per_buffer(unsigned long long int n) {
return pages_per_buffer_t(n);
}
void allocate_things(num_buffers_t num_buffers, pages_per_buffer_t pages_per_buffer) {
// do stuff...
}
template <typename S, typename T>
void allocate_things(S, T) = delete; // forbid calling with other types, eg. integer literals
int main() {
// now we see which is which ...
allocate_things(40_buffers, 22_pages_per_buffer);
// the following does not compile (see the 'deleted' function):
// allocate_things(40, 22);
// allocate_things(40, 22_pages_per_buffer);
// allocate_things(22_pages_per_buffer, 40_buffers);
}
Two good answers so far, one more: another approach would be to try leverage the type system wherever possible, and to create strong typedefs. For instance, using boost strong typedef (http://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/strong_typedef.html).
BOOST_STRONG_TYPEDEF(int , num_buffers);
BOOST_STRONG_TYPEDEF(int , num_pages);
void func(num_buffers b, num_pages p);
Calling func with arguments in the wrong order would now be a compile error.
A couple of notes on this. First, boost's strong typedef is rather dated in its approach; you can do much nicer things with variadic CRTP and avoid macros completely. Second, obviously this introduces some overhead as you often have to explicitly convert. So generally you don't want to overuse it. It's really nice for things that come up over and over again in your library. Not so good for things that come up as a one off. So for instance, if you are writing a GPS library, you should have a strong double typedef for distances in metres, a strong int64 typedef for time past epoch in nanoseconds, and so on.
(Note: post was originally tagged 'C`)
C99 onwards allows an extension to #Dietrich Epp idea: compound literal
struct things {
int num_buffers;
int pages_per_buffer;
int default_value
};
allocate_things(struct things);
// Use a compound literal
allocate_things((struct things){.default_value=80, .num_buffers=40, .pages_per_buffer=22});
Could even pass the address of the structure.
allocate_things(struct things *);
// Use a compound literal
allocate_things(&((struct things){.default_value=80,.num_buffers=40,.pages_per_buffer=22}));
You can't. That's why it is recommended to have as few function arguments as possible.
In your example you could have separate functions like set_num_buffers(int num_buffers), set_pages_per_buffer(int pages_per_buffer) etc.
You probably have noticed yourself that allocate_things is not a good name because it doesn't express what the function is actually doing. Especially I would not expect it to set a default value.
Just for completeness, you could use named arguments, when your call becomes.
void allocate_things(num_buffers=20, pages_per_buffer=40, default_value=20);
// or equivalently
void allocate_things(pages_per_buffer=40, default_value=20, num_buffers=20);
However, with the current C++ this requires quite a bit of code to be implemented (in the header file declaring allocate_things(), which must also declare appropriate external objects num_buffers etc providing operator= which return a unique suitable object).
---------- working example (for sergej)
#include <iostream>
struct a_t { int x=0; a_t(int i): x(i){} };
struct b_t { int x=0; b_t(int i): x(i){} };
struct c_t { int x=0; c_t(int i): x(i){} };
// implement using all possible permutations of the arguments.
// for many more argumentes better use a varidadic template.
void func(a_t a, b_t b, c_t c)
{ std::cout<<"a="<<a.x<<" b="<<b.x<<" c="<<c.x<<std::endl; }
inline void func(b_t b, c_t c, a_t a) { func(a,b,c); }
inline void func(c_t c, a_t a, b_t b) { func(a,b,c); }
inline void func(a_t a, c_t c, b_t b) { func(a,b,c); }
inline void func(c_t c, b_t b, a_t a) { func(a,b,c); }
inline void func(b_t b, a_t a, c_t c) { func(a,b,c); }
struct make_a { a_t operator=(int i) { return {i}; } } a;
struct make_b { b_t operator=(int i) { return {i}; } } b;
struct make_c { c_t operator=(int i) { return {i}; } } c;
int main()
{
func(b=2, c=10, a=42);
}
Are you really going to try to QA all the combinations of arbitrary integers? And throw in all the checks for negative/zero values etc?
Just create two enum types for minimum, medium and maximum number of buffers, and small medium and large buffer sizes. Then let the compiler do the work and let your QA folks take an afternoon off:
allocate_things(MINIMUM_BUFFER_CONFIGURATION, LARGE_BUFFER_SIZE, 42);
Then you only have to test a limited number of combinations and you'll have 100% coverage. The people working on your code 5 years from now will only need to know what they want to achieve and not have to guess the numbers they might need or which values have actually been tested in the field.
It does make the code slightly harder to extend, but it sounds like the parameters are for low-level performance tuning, so twiddling the values should not be perceived as cheap/trivial/not needing thorough testing. A code review of a change from
allocate_something(25, 25, 25);
...to
allocate_something(30, 80, 42);
...will likely get just a shrug/blown off, but a code review of a new enum value EXTRA_LARGE_BUFFERS will likely trigger all the right discussions about memory use, documentation, performance testing etc.

How can I write a function to modify a struct's member value without knowing the member's name ahead of time?

Say I have a struct that has a bunch of member variables. I want to write a function that will set the value of any of those members (along with a few other things, but I think that is beyond the scope of the question). Something like (but obviously not) this:
struct A
{
A() { /* do stuff */ }
bool a1;
bool a2;
bool a3;
void set_member(???);
bool get_member(???);
};
A a;
a.set_member(a1, true);
bool value = a.get_member(a1);
Now, my first thought is to use an array instead of a bunch of named variables. I would like to do that, but this is code that I would not like to touch in that way if I can help it (it is legacy). It has a constructor so I'm not even sure if it will maintain it's binary serializablility characteristics since it is not a POD. Even if it were a POD, I'm still not convinced as a1, a2 and a3 can have different alignment than that on an array of bools.
So, going back to the original question, is there a way of doing this? Perhaps with some template trick that I'm not aware of yet?
You can use a pointer-to-member:
void set_member(bool A::*var, bool value)
{
this->*var = value;
}
A a;
a.set_member(&A::a1, true);
A templatized version is straightforward:
template<typename T>
void set_member(T A::*var, T value)
{
this->*var = value;
}
But I don't see the reason for doing this if you already know the name of the variable.
If all contiguous members are the same data type, you could use pointer arithmetic:
void set_member(size_t var, bool val)
{
*(&a1+var) = val;
}
bool get_member(size_t var) const
{
return *(&a1+var);
}
A a;
a.set_member(1, true);
bool value = a.get_member(1);
But this can cause memory corruption or access violations if you use the wrong value of 'var'.

Calling templated function with type unknown until runtime

I have a this function to read 1d arrays from an unformatted fortran file:
template <typename T>
void Read1DArray(T* arr)
{
unsigned pre, post;
file.read((char*)&pre, PREPOST_DATA);
for(unsigned n = 0; n < (pre/sizeof(T)); n++)
file.read((char*)&arr[n], sizeof(T));
file.read((char*)&post, PREPOST_DATA);
if(pre!=post)
std::cout << "Failed read fortran 1d array."<< std::endl;
}
I call this like so:
float* new_array = new float[sizeof_fortran_array];
Read1DArray(new_array);
Assume Read1DArray is part of a class, which contains an ifstream named 'file', and sizeof_fortran_array is already known. (And for those not quite so familiar with fortran unformatted writes, the 'pre' data indicates how long the array is in bytes, and the 'post' data is the same)
My issue is that I have a scenario where I may want to call this function with either a float* or a double*, but this will not be known until runtime.
Currently what I do is simply have a flag for which data type to read, and when reading the array I duplicate the code something like this, where datatype is a string set at runtime:
if(datatype=="float")
Read1DArray(my_float_ptr);
else
Read1DArray(my_double_ptr);
Can someone suggest a method of rewriting this so that I dont have to duplicate the function call with the two types? These are the only two types it would be necessary to call it with, but I have to call it a fair few times and I would rather not have this duplication all over the place.
Thanks
EDIT:
In response to the suggestion to wrap it in a call_any_of function, this wouldnt be enough because at times I do things like this:
if(datatype=="float")
{
Read1DArray(my_float_ptr);
Do_stuff(my_float_ptr);
}
else
{
Read1DArray(my_double_ptr);
Do_stuff(my_double_ptr);
}
// More stuff happening in between
if(datatype=="float")
{
Read1DArray(my_float_ptr);
Do_different_stuff(my_float_ptr);
}
else
{
Read1DArray(my_double_ptr);
Do_different_stuff(my_double_ptr);
}
If you think about the title you will realize that there is a contradiction in that the template instantiation is performed at compile time but you want to dispatch based on information available only at runtime. At runtime you cannot instantiate a template, so that is impossible.
The approach you have taken is actually the right one: instantiate both options at compile time, and decide which one to use at runtime with the available information. That being said you might want to think your design.
I imagine that not only reading but also processing will be different based on that runtime value, so you might want to bind all the processing in a (possibly template) function for each one of the types and move the if further up the call hierarchy.
Another approach to avoid having to dispatch based on type to different instantiations of the template would be to loose some of the type safety and implement a single function that takes a void* to the allocated memory and a size argument with the size of the type in the array. Note that this will be more fragile, and it does not solve the overall problem of having to act on the different arrays after the data is read, so I would not suggest following this path.
Because you don't know which code path to take until runtime, you'll need to set up some kind of dynamic dispatch. Your current solution does this using an if-else which must be copied and pasted everywhere it is used.
An improvement would be to generate a function that performs the dispatch. One way to achieve this is by wrapping each code path in a member function template, and using an array of member function pointers that point to specialisations of that member function template. [Note: This is functionally equivalent to dynamic dispatch using virtual functions.]
class MyClass
{
public:
template <typename T>
T* AllocateAndRead1DArray(int sizeof_fortran_array)
{
T* ptr = new T[sizeof_fortran_array];
Read1DArray(ptr);
return ptr;
}
template <typename T>
void Read1DArrayAndDoStuff(int sizeof_fortran_array)
{
Do_stuff(AllocateAndRead1DArray<T>(sizeof_fortran_array));
}
template <typename T>
void Read1DArrayAndDoOtherStuff(int sizeof_fortran_array)
{
Do_different_stuff(AllocateAndRead1DArray<T>(sizeof_fortran_array));
}
// map a datatype to a member function that takes an integer parameter
typedef std::pair<std::string, void(MyClass::*)(int)> Action;
static const int DATATYPE_COUNT = 2;
// find the action to perform for the given datatype
void Dispatch(const Action* actions, const std::string& datatype, int size)
{
for(const Action* i = actions; i != actions + DATATYPE_COUNT; ++i)
{
if((*i).first == datatype)
{
// perform the action for the given size
return (this->*(*i).second)(size);
}
}
}
};
// map each datatype to an instantiation of Read1DArrayAndDoStuff
MyClass::Action ReadArrayAndDoStuffMap[MyClass::DATATYPE_COUNT] = {
MyClass::Action("float", &MyClass::Read1DArrayAndDoStuff<float>),
MyClass::Action("double", &MyClass::Read1DArrayAndDoStuff<double>),
};
// map each datatype to an instantiation of Read1DArrayAndDoOtherStuff
MyClass::Action ReadArrayAndDoOtherStuffMap[MyClass::DATATYPE_COUNT] = {
MyClass::Action("float", &MyClass::Read1DArrayAndDoOtherStuff<float>),
MyClass::Action("double", &MyClass::Read1DArrayAndDoOtherStuff<double>),
};
int main()
{
MyClass object;
// call MyClass::Read1DArrayAndDoStuff<float>(33)
object.Dispatch(ReadArrayAndDoStuffMap, "float", 33);
// call MyClass::Read1DArrayAndDoOtherStuff<double>(542)
object.Dispatch(ReadArrayAndDoOtherStuffMap, "double", 542);
}
If performance is important, and the possible set of types is known at compile time, there are a few further optimisations that could be performed:
Change the string to an enumeration that represents all the possible data types and index the array of actions by that enumeration.
Give the Dispatch function template parameters that allow it to generate a switch statement to call the appropriate function.
For example, this can be inlined by the compiler to produce code that is (generally) more optimal than both the above example and the original if-else version in your question.
class MyClass
{
public:
enum DataType
{
DATATYPE_FLOAT,
DATATYPE_DOUBLE,
DATATYPE_COUNT
};
static MyClass::DataType getDataType(const std::string& datatype)
{
if(datatype == "float")
{
return MyClass::DATATYPE_FLOAT;
}
return MyClass::DATATYPE_DOUBLE;
}
// find the action to perform for the given datatype
template<typename Actions>
void Dispatch(const std::string& datatype, int size)
{
switch(getDataType(datatype))
{
case DATATYPE_FLOAT: return Actions::FloatAction::apply(*this, size);
case DATATYPE_DOUBLE: return Actions::DoubleAction::apply(*this, size);
}
}
};
template<void(MyClass::*member)(int)>
struct Action
{
static void apply(MyClass& object, int size)
{
(object.*member)(size);
}
};
struct ReadArrayAndDoStuff
{
typedef Action<&MyClass::Read1DArrayAndDoStuff<float>> FloatAction;
typedef Action<&MyClass::Read1DArrayAndDoStuff<double>> DoubleAction;
};
struct ReadArrayAndDoOtherStuff
{
typedef Action<&MyClass::Read1DArrayAndDoOtherStuff<float>> FloatAction;
typedef Action<&MyClass::Read1DArrayAndDoOtherStuff<double>> DoubleAction;
};
int main()
{
MyClass object;
// call MyClass::Read1DArrayAndDoStuff<float>(33)
object.Dispatch<ReadArrayAndDoStuff>("float", 33);
// call MyClass::Read1DArrayAndDoOtherStuff<double>(542)
object.Dispatch<ReadArrayAndDoOtherStuff>("double", 542);
}

choose correct template specialization at run-time

I have
template <int i> struct a { static void f (); };
with specializations done at different places in the code. How can I call the correct a<i>::f for an i known only at runtime?
void f (int i) { a<i>::f (); } // won't compile
I don't want to list all possible values of i in a big switch.
Edit:
I thought of something like
#include <iostream>
template <int i> struct a { static void f (); };
struct regf {
typedef void (*F)();
enum { arrsize = 10 };
static F v[arrsize];
template < int i > static int apply (F f) {
static_assert (i < arrsize, "");
v[i] = a<i>::f;
return 0;
}
};
regf::F regf::v[arrsize];
template <int i> struct reg { static int dummy; };
template <int i> int reg<i>::dummy = regf::apply<i> ();
void f (int i) { return regf::v[i] (); }
#define add(i) \
template <> struct a<i> : reg<i> { \
static void f () { std::cout << i << "\n"; } \
};
add(1)
add(3)
add(5)
add(7)
int main () {
f (3);
f (5);
}
but it crashes (did I miss something to force an instantiation?), and I don't like that dummy is not static const (and uses memory) and of course that arrsize is bigger than necessary.
Actual problem: To have a function generate (int i) that calls a<i>::generate () to generate an instance of class a<i> for an i given only at run-time. The design (classes a<i>) is given, they inherit from a base class and more specializations of a could be added at any time anywhere in the code, but I don't want to force everyone to change my generate (i) manually as that could be forgotten easily.
I am not sure that this is the best solution that you can get, as there might be better designs, at any rate you can use some metaprogramming to trigger the instantiation and registry of the functions:
// in a single cpp file
namespace {
template <unsigned int N>
int register_a() { // return artificially added
register_a<N-1>(); // Initialize array from 0 to N-1
regf::v[N] = &a<N>::f; // and then N
return N;
}
template <>
int register_a<0>() {
regf::v[0] = &a<0>::f; // recursion stop condition
return 0;
}
const int ignored = register_a<regf::arrsize>(); // call it
}
That code will instantiate the functions and register pointers to the static member functions. The fake return type is required to be able to force execution of the function in an static context (by means of using that function to initialize a static value).
This is quite prone to the static initialization fiasco. While regf::v is ok, any code that depends on regf::v containing the appropriate pointers during static initialization is bound to fail. You can improve this with the usual techniques...
From the bits and pieces that you have actually posted, my guess is that you are trying to use an abstract factory with automated registration from each one of the concrete factories. There are better ways of approaching the problem, but I think that this answer solves your question (I am unsure on whether this does solve your problem).
You have to. Templates are resolved and instantiated at compile-time. Apart from that, a switch needn't be inefficient. It usually compiles to a lookup table with very little overhead.
You can, however, use recursive template magic to have nested if/else blocks to replace the switch generated for you by the compiler. But a plain switch should be much more readable. Unless of course you have literally thousands of cases.
In either case, you need to know the set of values that i can have at compilation time since the compiler needs to know which templates to instantiate.
You can't pick a template specialization at runtime, they're by definition chosen at compile time.
The usual ways to solve the dispatch problem you're looking at are switch (as you surmised) or a vector or map of int to function pointer.
No, compiler needs to the instantiation of the template at compile time, for that it needs to know the value of i at compile time.
You can't as template instantiation is done at compile time.