I have a template function that I want to store a pointer to inside a std::vector.
The function looks like this:
template<typename T> void funcName(T& aT, std::vector<std::string>& fileName){...}
Now I want to store multiple pointers to functions of this kind inside a std::vector. For non-template functions I would do it like this:
typedef std::vector<std::string> string_vt;
typedef void func_t(T&, string_vt&);
typedef func_t* funcPointer;
typedef std::vector<funcPointer> funcPointer_vt;
But what is the correct syntax for template functions? How can I store them?
EDIT: First of all, thank you for your fast response. This was my first Question on Stack Overflow, so I am sorry for not providing enough information.
The set of T is finite, it can either be of type ClassA or type classB. In these function templates I want to do changes to T (so either ClassA or ClassB) with some hard coded data. I have 8 of these functions, which basically initiate a default constructed T with data specific to the function. In my program, I want to initiate 2*8 default constructed T's (8 ClassA and 8 ClassB). Therefore I run a for loop, calling one function after the other, to initiate my T objects with the function's body data.
for(int i = 0; i < initT.size(); ++i){
init_T[i]<T>(someT, fileName);
}
The for loop has as much iterations as there are function pointers inside the vector. At every iteration the function is called with some previously default constructed T and some other parameter. At the end the goal is to have 8 initiated T's with data specific to the function.
EDIT2: In case it helps, here is some actual source code. Inside the following function template I want to access my vector of function pointers in order to call the respective function.
template<typename T_Relation, typename T_Relation_Vec, bool row>
void bulk_load(initRelation_vt& aInitFunctions, T_Relation_Vec& aRel_Vec, const bool aMeasure, const uint aRuns, const char* aPath)
{
for(size_t i = 0; i < aRuns; ++i)
{
MemoryManager::freeAll();
aRel_Vec.clear();
string_vt fileNames;
for(size_t j = 0; j < aInitFunctions.size(); ++j)
{
aRel_Vec.emplace_back(T_Relation());
aInitFunctions[j]<T_Relation>(aRel_Vec[j], fileNames);
BulkLoader bl(fileNames[j].c_str(), tuples, aRel_Vec[j], delimiter, seperator);
Measure lMeasure;
if(aMeasure)
{
lMeasure.start();
}
try
{
bl.bulk_load();
if(row)
{
BulkInsertSP bi;
bi.bulk_insert(bl, aRel_Vec[j]);
}
else
{
BulkInsertPAX bi;
bi.bulk_insert(bl, aRel_Vec[j]);
}
}
catch(std::exception& ex)
{
std::cerr << "ERROR: " << ex.what() << std::endl;
}
lMeasure.stop();
if(aMeasure)
{
std::ofstream file;
file.open (aPath, std::ios::out | std::ios::app);
//print_result(file, flag, lMeasure.mTotalTime());
file.close();
}
}
}
}
This line is where the vector of function template pointers is accessed.
aInitFunctions[j]<T_Relation>(aRel_Vec[j], fileNames);
Templates are an advanced technique for static polymorphism. In a typed language, like C++, without static polymorphism you would have to separately define every entity used and precisely indicate every entity referred to.
Mechanisms of static polymorphism in C++ allow to automate indication of function or method and defer it until build via overloading. It allows you to define multiple entities sharing some characteristics at once via templates and defer definition of particular specializations until build, inferred from use.
(Notice that in various scenarios, static polymorphism allows separate code, so that changes to use and to definition are independent, which is very useful.)
The important implication of this mechanism is that every specialization of your template may be of different type. It is unclear, as of when I'm responding, whether you want to store pointers to a single or multiple types of specialization in one type of container. The possibilities depend also on parameter and result types of the function template.
A function in C++ has a type that is a combination of list of its parameter types and its return type. In other words, two functions that take and return the same types are of the same type. If your function template neither took or returned template parameter type (ie. T) nor templated type (eg. std::vector<T>), every specialization of this function template would be taking and returning the same types and would therefore be a function of the same type.
template <typename T>
int func() { ... }
This (arguably useless) function template takes no arguments and returns int, whatever T is used to specialize the template. Therefore a pointer to it could be used wherever the parameter is defined as int (*f)(). In this case you could keep pointer to any specialization in one vector.
typedef std::vector<std::string> string_vt;
typedef int func_t();
typedef func_t* funcPointer;
typedef std::vector<funcPointer> funcPointer_vt;
funcPointer x = &func<int>;
funcPointer y = &func<float>;
As can be seen, every specialization of your function template is of the same type and both pointers fit in the same container.
Next case - what if function header depends on a template parameter? Every specialization would have a different signature, that is a different function type. The pointers to all of them would be of different types - so it wouldn't be possible to even typedef this pointer once.
template <typename T>
void func(std::vector<T> param) { ... }
In this case function template specialization is of different type depending on T used to specialize.
typedef int func_t_int(std::vector<int>);
typedef func_t_int* funcPointerInt;
typedef std::vector<funcPointerInt> funcPointerInt_vt;
typedef float func_t_float(std::vector<float>);
typedef func_t_float* funcPointerFloat;
typedef std::vector<funcPointerFloat> funcPointerFloat_vt;
funcPointerInt x = &func<int>;
funcPointerFloat x = &func<float>;
Specializations are of different types, because they take different type of vectors. Pointers do not fit in the same container.
It's mention-worthy at this point, that in this case it's not necessary to define every pointer type separately. They could be a template type:
template <typename T>
using funcPointer = void (*)(std::vector<T>);
Which now allows funcPointer<int> to be used as a type qualifier, in place of earlier funcPointerInt.
funcPointer<float> y = &func<float>;
In more complicated situations a template could be created, whose every specialization is of a different type, and then would use a single instance of concrete vector to store various pointers to functions of type of only one of the specializations of your template. Although a simple template like in the example can only produce a single function per type, because every specialization yields one type of function and one function of that type, it's not impossible to conceive a scenario where various pointers to functions are obtained, both to specializations and usual functions, perhaps from various sources. So the technique could be useful.
But yet another scenario is that despite every specialization of the template being of different type, there's a need to store pointers to various specializations in single std::vector. In this case dynamic polymorphism will be helpful. To store values of different types, fe. pointers to functions of different types, in one type of variable, requires inheritance. It is possible to store any subclass in a field defined as superclass. Note however, that this is unlikely to accomplish anything really and probably not what you're really looking for.
I see two general possibilities now. Either use a class template with a method, which inherits from a non-template class.
template <typename T>
class MyClass : BaseClass
{
public:
T operator()(const T& param, int value);
}
MyClass<int> a;
MyClass<float> b;
BaseClass* ptr = &a;
ptr = &b;
While every specialization of this class may be of a different type, they all share superclass BaseClass, so a pointer to a BaseClass can actually point to any of them, and a std::vector<funcPointerBase> can be used to store them. By overloading operator() we have create an object that mimics a function. The interesting property of such a class is that it can have multiple instances created with parameter constructors. So effectively class template produces specializations of multiple types, and in turn every specialized class can produce instances of varying parametrization.
template <typename T>
class MyClass : BaseClass
{
int functor_param;
public:
MyClass(int functor_param);
T operator()(const T& param, int value);
}
This version allows creation of instances that work differently:
MyClass<int> a(1);
MyClass<int> b(2);
MyClass<float> c(4);
MyClass<int>* ptr = &a;
ptr = &b;
ptr = &c;
I am no expert on functors, just wanted to present the general idea. If it seems interesting, I suggest researching it now.
But technically we're not storing function pointers, just regular object pointers. Well, as stated before, we need inheritance to use one type of variable to store values of various types. So if we're not using inheritance to exchange our procedural functions for something dynamically polymorphic, we must do the same to pointers.
template <typename T>
T func(std::pair < T, char>) {}
template <typename T>
using funcPointer = T(*)(std::pair<T, char>);
template <typename T>
class MyPointer : BasePointer
{
funcPointer<T> ptr;
public:
MyPointer(funcPointer<T> ptr);
T()(std::pair <T, char>) operator*(std::pair <T, char> pair)
{
*ptr(pair);
}
};
This, again, allows creation of single std::vector<BasePointer> to store all possible pseudo-function-pointers.
Now the very important bit. How would You go about calling those, in either scenario? Since in both cases they are stored in a single std::vector<>, they are treated as if they were of the base type. A specific function call needs parameters of specific type and returns a specific type. If there was anything that all subclasses can do in the same way, it could be exposed by defining such a method in base class (in either scenario using functors or pointer..ors?), but a specific specialized function call is not that kind of thing. Every function call that You would want to perform in the end, after all this struggle, would be of a different type, requiring different type of parameters and/or returning different type of value. So they could never all fit into the same place in usual, not templated code, the same circumstances in execution. If they did, then dynamic polymorphism wouldn't be necessary to solve this problem in the first place.
One thing that could be done - which is greatly discouraged and probably defeats the purpose of dynamic polymorphism - is to detect subclass type at runtime and proceed accordingly. Research that, if you're convinced you have a good case for using this. Most likely though, it's probably a big anti-pattern.
But technically, anything you may want to do is possible somehow.
If I have correctly understood you, I may have a really simple and efficient solution:
template<class...Ts>
struct functor{
//something like a dynamic vtable
std::tuple<void(*)(Ts&,std::vector<std::string>&)...> instantiated_func_ptr;
template<class T>
void operator ()(T& aT,std::vector<std::string>& fileName){
get<void(*)(T&,std::vector<std::string>&)>(instantiated_func_ptr)
(aT,fileName);
}
};
VoilĂ !!
Until c++17, get<typename> is not defined so we have to define it (before the definition of the template functor above):
template<class T,class...Ts>
struct find_type{
//always fail if instantiated
static_assert(sizeof...(Ts)==0,"type not found");
};
template<class T,class U,class...Ts>
struct find_type<T,U,Ts...>:std::integral_constant<size_t,
find_type<T,Ts...>::value+1>{};
template<class T,class...Ts>
struct find_type<T,T,Ts...>:std::integral_constant<size_t,0>{};
template<class T,class...Ts>
constexpr decltype(auto) get(const std::tuple<Ts...>& t){
return get<find_type<T,Ts...>::value>(t);
}
And an example to show how to use it:
struct A{
void show() const{
std::cout << "A" << "\n";
}
};
struct B{
void show() const{
std::cout << "B" << "\n";
}
};
template<class T>
void func1(T& aT,std::vector<std::string>& fileName){
std::cout << "func1: ";
aT.show();
}
template<class T>
void func2(T& aT,std::vector<std::string>& fileName){
std::cout << "func2: ";
aT.show();
}
template<class T>
void func3(T& aT,std::vector<std::string>& fileName){
std::cout << "func3: ";
aT.show();
}
using functorAB = functor<A,B>;
int main(){
auto functor1=functorAB{{func1,func1}};//equivalent to functorAB{{func1<A>,func1<B>}}
auto functor2=functorAB{{func2,func2}};
auto functor3=functorAB{{func3,func3}};
auto v=std::vector<functorAB>{functor1,functor2,functor3};
auto a=A{};
auto b=B{};
auto fileNames = std::vector<std::string>{"file1","file2"};
for(auto& tf:v)
tf(a,fileNames);
for(auto& tf:v)
tf(b,fileNames);
}
In practice it is just a reproduction of the virtual call mechanism,
the tuple in functor is kind of virtual table. This code is not
more efficient than if you had written an abstract functor with virtual
operator() for each of your class A and B and then implemented it for each of
your functions... but it is much more concise, easier to maintain and may produce less binary code.
Related
Is it possible to make an array of a struct with template type fields?
template<typename T>
struct MyStruct {
T *pField;
};
MyStruct< ?? > mystruct_arr[] = {
{ pFieldOfType1 },
{ pFieldOfType2 },
};
The above obviously doesn't work, but is it possible with other techniques?
I am trying to loop through the array mystruct_arr and call this function on every struct row:
template<typename T>
void SetupField(T &pSourceField, ...)
{
Base *field = ...->findBaseFieldFromDatabase(...);
...
pSourceField = static_cast<T>(field);
...
}
The reason is to try to refactor a very repetitive piece of code where I have to static_cast a long list of different types according to a few different arguments, without making it overly complicated.
A template is not a class, or a struct. It can be thought of as a blueprint, or a recipe, for a class or a struct that gets created when the template gets instantiated.
A template becomes an actual class or a struct only when it is instantiated, by specifying the required template parameters:
MyStruct<int>
Now you have an actual, living, breathing class here. But a MyStruct<int> would be a completely different class than MyStruct<char>. Without specifying the template parameters, MyStruct is not a class, or a struct, or anything that takes up a single byte of RAM. It's just a template for some struct or class.
But with template parameters, such as MySutrct<int>, this becomes an actual class with fields, and perhaps methods. Now that you have a class you can certainly have an array of these, now:
MyStruct<int> mystruct_arr[] = {
};
Or you could have a different array of MyStruct<char>s:
MyStruct<char> mystruct_arr2[] = {
};
But you can't have an array that contains both of these for the same, exact, precise reason that you can't have a single array containing a smorgasbord of different types and classes. You can't have an array that contains both chars, ints, floats, pointers, or various classes. An array always contains values of the same type/class. So pick one particular MyStruct<whatever>, and make an array out of it, that's all you can do.
But you can also declare another structure, now:
struct many_structs {
MyStruct<int> int_struct;
MyStruct<char> char_struct;
// ...
};
This sort of starts to look like an array you would like to have. But it's not an array. It's just an ordinary struct; and instead of using an array index to access a particular template instance, you would refer to the struct member directly.
You could, with some additional work, specialize std::get for your structure, and make this structure look like an array. But now you just realized that you reinvented std::tuple, and can simply to do this:
std::tuple<MyStruct<int>, MyStruct<char>> mystruct_tuple;
Finally, the closest approximation to what you're trying to do is possible only with some additional work, and with a C++ compiler that supports C++17, by declaring an array containing std::anys, or perhaps std::variants. If the array should only contain an a limited enumeration of template instances, std::variant gives the most type-safety, and convenience:
std::variant<MyStruct<int>, MyStruct<char>> mystruct_arr[]={
};
The resulting array contains only these two particular template instances. And with std::any, the screws get loosened further but you'll have to do more work to use and access each value in the array.
You think you want an array of templates.
What you really want is an array of types you can call a particular template function on.
The first is not possible. The second is called type erasure in C++.
template<class T>
using setup_fptr=void(*)(T &, Foo)
using gen_setup_ptr=void(*)(void*, Foo);
template<class T>
setup_ptr<T> get_setup(){ return SetupField<T>; }
template<class T>
gen_setup_ptr get_gen_setup(){
return [](void* p, Foo f){ get_setup<T>( *static_cast<T*>(p), f ); };
}
struct can_setup {
void* ptr=0;
gen_setup_ptr f=0;
can_setup(can_setup const&)=default;
can_setup& operator=(can_setup const&)=default;
can_setup()=default;
explicit operator bool() const{return f;}
template<class T>
can_setup(T* pt):
ptr(pt),
f( get_gen_setup<T>() )
{}
void setup( Foo foo ) const {
f(ptr, foo );
}
};
store an array of can_setup. Loop over them calling .setup(foo).
Foo is a placeholder for whatever other args you are using.
This technique is known as type erasure; we forget (erase) everything about T except that we can setup it.
I am struggling with allowing user to select data type template will be created as.
Since template type must be defined on compile, I must specify data type template will use eg(string,int, so on), but that means I cannot change it latter on, from lets say string to int even if my template supports it, because template class object was declared as string.
My class declaration below:
template <class T>
class MyHashTable
{
public:
string deleted="deleted";
unsigned short tableSize;
// array of vectors, hash table container
vector<T>* myTable;
vector<T>* deletionTable;
MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]), deletionTable(new vector<T>[tableSize])
{
this->tableSize=tableSize;
}
object declaration outside class
MyHashTable <string>* myChainedTable=NULL ;
string tableType;
object initialization
if (myChainedTable)
{
delete myChainedTable;
myChainedTable=NULL;
}
getType();
if (!myChainedTable)
{
if (tableType=="string")
myChainedTable= new MyHashTable<string>(length);
if (tableType=="char")
MyHashTable<char> myChainedTable(length); // no difference with or without using new keyword
if (tableType=="double")
MyHashTable<double> myChainedTable(length);
if (tableType=="float")
MyHashTable<float> myChainedTable(length);
if (tableType=="int")
MyHashTable<int> myChainedTable(length);
cout<<tableType<<" table of size "<< length<<" created"<<endl;
I attempted passing class object to functions instead of having it as global variable, but couldnt get it work either.
What I really need is single template object that can have: int,string,char,double,float types, I have 3 functions that need to have access to template class object, and having 5 different objects and 200 lines of if statements for each situation sounds like worst possible solution.
I been stuck on this for a while and just cant figure out how to do it and any help will be appreciated.
void getType()
{
cout<<"Enter table type, types available: int, char, float, double, string.\n";
tableType=getInput();
while((tableType != "int")&&(tableType !="float")&&(tableType !="double")&&(tableType!="char")&&(tableType !="string"))
{
cout<<"Invalid type, please try again "<<endl;;
tableType=getInput();
}
}
Your question is at the boarder between templates and variants.
The template is compile time. So you have to choose at compile time the type you want for your object. Your conditional approach can't work (see comments to question).
On the other side, you seem to need a dynamic choice of type at runtime.
If you want to go on on template way: (edit based on comments)
You'd need to have all the templates inherit from a single polymorphic base class (one common interface with virtual functions). Example:
class MyHashBase // common base class for all templates
{
public:
virtual void addElement(void *ptrelem) = 0; // adding an element must be implemented by template. With void* since future template type unknown from base class
virtual void displayAll() = 0;
};
The templates would need then implement the virtual functions:
template <class T>
class MyHashTable : public MyHashBase
{
public:
unsigned short tableSize;
vector<T>* myTable; // I leave it as it is, but you could implement these as vector<T> instead of vector<T>*
vector<T>* deletionTable;
MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]), deletionTable(new vector<T>[tableSize]), tableSize(tableSize)
{ }
void addElement(void* ptrelem)
{ myTable->push_back(*reinterpret_cast<T*>(ptrelem)); } // reinterpret the void* of the common interface as a T*
void displayAll()
{ copy(myTable->begin(), myTable->end(), ostream_iterator<T>(cout, "\n")); }
};
You could then have your myChainedTable be a pointer to the common base type, and intialise this pointer in the way you did with the string case (i.e. using new).
MyHashBase *myChainedTable = nullptr;
//...
if (tableType == "string")
myChainedTable = new MyHashTable<string>(length);
else if (tableType == "double")
myChainedTable = new MyHashTable<double>(length);
//...
You could then use the common API, for example if tableType is "double":
double d1 = 3.1415, d2 = 1.4142;
myChainedTable->addElement(&d1); // ATTENTION: you must ensure to provide pointer to the correct data type
myChainedTable->addElement(&d2);
myChainedTable->displayAll();
You'll certainly have a coupe of if required in the calling code, but you could reduce them to minimum by carefully designing the base class (for example, you could add a virtual clone function, to duplicate the data without need to know the type by the caller).
However, using a single signature for the common functions of the base class is cumbersome. To make the virtualisation possible you need to pass parameters through void* pointer which is not so nice and rather error prone.
Alternate way with variants
You could also use boost variants which are meant for managing objects with dynamic definition of types.
In this case you would not need template for your own data structure. You would create a MyHashTable with elements of type boost::variant< int, std::string, ... >.
You could then access to the right value of the object if you know its type (as in your myChainedTable) by using: boost::get<int> (element) (or boost::get<string>(), ...).
If you don't know the type on an element you could use the concept of "visitor" to chose automatically the appropriate function to exectue depending on the type.
Edit: alternate way with unions:
If you're not allowed to use variants another alternative could be use a union. I don't know the topic of you rassignment, but you have the choice whether you use a union to define the elements (like the variants, without templates) or to use a template type as you did, but define myChainedTable to be a union of pointers to the different template instantiations. But yes, it requires a lot of ifs...
Templates are resolved at compile time. Your container type is resolved at runtime. Templates are clearly not the solution here. The first thing that comes to my mind is a combination of boost::any and std::vector instead.
I'm well aware of boost::any and boost::variant, but in this instance they don't fit my needs.
Normally, to contain an object of unknown type, one would derive it from a common base and access the instance through virtual methods. But, what can one do if it's impossible to use a common base?
I know that in this example you would have to know the contained type, but bear with me. std::vector is a template class with top level class also being a template. As far as I know it cannot be given a non-template base without modifying the STL headers. Now, lets say I want to create a vector of a single type but the containing class doesn't care about the type, but it does require access to some of the 'common' methods, size() and pop_back() for example.
Using boost::any, the type has been erased, making it almost impossible to dereference the contained object. boost::variant and tuple require knowing before hand what types may be inserted, causing the containing class to itself be a template.
What I have so far is something like this:
struct container
{
virtual ~container() = 0;
virtual void pop_back() = 0;
virtual size_t size() = 0;
...
}
template < typename T >
struct contained
{
std::vector< T > _vec;
contained ( size_t n, T _what ) : _vec( n, _what ) {}
virtual void pop_back() { _vec.pop_back(); }
...
}
class some_class
{
container* _cont;
template < typename T >
void create ( T _first ) { _cont = new contained< T >(1,_first); }
...
}
Here the client can call on create() and the template parameter should be determined automatically. Not a great example I know, but I'm trying to hide the template parameters from the client. Without doing this, some_class would have to also keep track of what type is being stored.
My method relies on virtual calls which causes a performance loss, especially when the internal class has virtual methods of it's own.
Are there any other types of containers that would better suit my needs?
Ideally, I'd like something like this
container = std::vector< T >;
container.pop_back();
container.push_back( T2 ); // compile error if types don't match
Where internally it would track the type and do a simple cast rather than rely on virtual methods. Almost like auto with the difference being that once declared it's type can change.
Edit:
In reality, I want to create a wrapper around std::basic_filebuf. This wrapper class opens the file with char,wchar_t or unsigned long based on the BOM. The wrapper is also derived from basic_filebuf with the template parameter being whatever the client chooses. Internally, it converts unicode code points from the file to the clients desired encoding. The problem arises when storing the internal basic_filebuf because it can be declared with any type as the template parameter. I don't want to use template specialization because I want the client to be able to pass in their own basic_filebuf instance.
Must be VS2010 compatible, which has limited features from C++11.
This cannot be combined with compile-time type checking. Based on your "ideally" example:
container c;
if (thingKnownAtRunTime()) {
c = vector<int>;
} else {
c = vector<string>;
}
c.push_back("hello world");
For the filebuf case, though, you might get good enough with something like (warning: untested)
template<typename FILEBUF>
void gensputc(FILEBUF* fb, long long c) {
FILEBUf::char_type c2 = smart_convert<FILEBUf::char_type>(c);
fb->sputc(c2);
}
class FileBufWrapper {
public:
template<typename FILEBUF> FileBufWrapper(FILEBUF* fb) {
fb_ = fb;
sputc_ = gensputc<FILEBUF>;
}
void sputc(long long c) {
sputc_(fb_,c);
}
private:
typedef void(*sputc_t)(void*, long long);
sputc_t sputc_;
void* fb_;
};
The smart_convert function throws a runtime exception if the value cannot be converted to the char type. Also, this needs to be done for every function you intend to call.
If you have access to c++11's std::function and std::bind, this can be made a little cleaner, especially for the cases where you don't need to convert anything.
I need to store multiple types of a template class in a single vector.
Eg, for:
template <typename T>
class templateClass{
bool someFunction();
};
I need one vector that will store all of:
templateClass<int> t1;
templateClass<char> t2;
templateClass<std::string> t3;
etc
As far as I know this is not possible, if it is could someone say how?
If it isn't possible could someone explain how to make the following work?
As a work around I tried to use a base, non template class and inherit the template class from it.
class templateInterface{
virtual bool someFunction() = 0;
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction();
};
I then created a vector to store the base "templateInterface" class:
std::vector<templateInterface> v;
templateClass<int> t;
v.push_back(t);
This produced the following error:
error: cannot allocate an object of abstract type 'templateInterface'
note: because the following virtual functions are pure within 'templateInterface'
note: virtual bool templateInterface::someFunction()
To fix this error I made the function in templateInterface not a pure virtual by providing a function body, this compiled but when calling the function the overide is not used, but instead the body in the virtual function.
Eg:
class templateInterface{
virtual bool someFunction() {return true;}
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction() {return false;}
};
std::vector<templateInterface> v;
templateClass<int> i;
v.push_back(i);
v[0].someFunction(); //This returns true, and does not use the code in the 'templateClass' function body
Is there any way to fix this so that the overridden function is used, or is there another workaround to store multiple template types in a single vector?
Why your code doesn't work:
Calling a virtual function on a value doesn't use polymorphism. It calls the function which is defined for the type of this exact symbol as seen by the compiler, not the runtime type. When you insert sub types into a vector of the base type, your values will be converted into the base type ("type slicing"), which is not what you want. Calling functions on them will now call the function as defined for the base type, since not it is of that type.
How to fix this?
The same problem can be reproduced with this code snippet:
templateInterface x = templateClass<int>(); // Type slicing takes place!
x.someFunction(); // -> templateInterface::someFunction() is called!
Polymorphism only works on a pointer or reference type. It will then use the runtime type of the object behind the pointer / reference to decide which implementation to call (by using it's vtable).
Converting pointers is totally "safe" with regard to type slicing. Your actual values won't be converted at all and polymorphism will work as expected.
Example, analogous to the code snippet above:
templateInterface *x = new templateClass<int>(); // No type slicing takes place
x->someFunction(); // -> templateClass<int>::someFunction() is called!
delete x; // Don't forget to destroy your objects.
What about vectors?
So you have to adopt these changes in your code. You can simply store pointers to actual types in the vector, instead of storing the values directly.
When working with pointers you also have to care about deleting your allocated objects. For this you can use smart pointers which care about deletion automatically. unique_ptr is one such smart pointer type. It deletes the pointee whenever it goes out of scope ("unique ownership" - the scope being the owner). Assuming the lifetime of your objects is bound to the scope this is what you should use:
std::vector<std::unique_ptr<templateInterface>> v;
templateClass<int> *i = new templateClass<int>(); // create new object
v.push_back(std::unique_ptr<templateInterface>(i)); // put it in the vector
v.emplace_back(new templateClass<int>()); // "direct" alternative
Then, call a virtual function on one of these elements with the following syntax:
v[0]->someFunction();
Make sure you make all functions virtual which should be possible to be overridden by subclasses. Otherwise their overridden version will not be called. But since you already introduced an "interface", I'm sure you are working with abstract functions.
Alternative approaches:
Alternative ways to do what you want is to use a variant type in the vector. There are some implementations of variant types, the Boost.Variant being a very popular one. This approach is especially nice if you don't have a type hierarchy (for example when you store primitive types). You would then use a vector type like std::vector<boost::variant<int, char, bool>>
Polymorphism only works through pointers or references. You'll
need the non-template base. Beyond that, you'll need to decide
where the actual objects in container will live. If they're all
static objects (with sufficient lifetime), just using
a std::vector<TemplateInterface*>, and inserting with
v.push_back(&t1);, etc., should do the trick. Otherwise,
you'll probably want to support cloning, and keep clones in the
vector: preferably with Boost pointer containers, but
std::shared_ptr can be used as well.
The solutions given so far are fine though be aware that in case you were returning the template type other than bool in your example , none of these would help as the vtable slots would not be able to be measured before hand. There are actually limits , from a design point of view , for using a template oriented polymorphic solution.
Solution nr. 1
This solution inspired by Sean Parent's C++ Seasoning talk. I highly recommend to check it out on youtube. My solution simplified a bit and the key is to store object in method itself.
One method only
Create a class that will invoke method of stored object.
struct object {
template <class T>
object(T t)
: someFunction([t = std::move(t)]() { return t.someFunction(); })
{ }
std::function<bool()> someFunction;
};
Then use it like this
std::vector<object> v;
// Add classes that has 'bool someFunction()' method
v.emplace_back(someClass());
v.emplace_back(someOtherClass());
// Test our vector
for (auto& x : v)
std::cout << x.someFunction() << std::endl;
Several methods
For several methods use shared pointer to share object between methods
struct object {
template <class T>
object(T&& t) {
auto ptr = std::make_shared<std::remove_reference_t<T>>(std::forward<T>(t));
someFunction = [ptr]() { return ptr->someFunction(); };
someOtherFunction = [ptr](int x) { ptr->someOtherFunction(x); };
}
std::function<bool()> someFunction;
std::function<void(int)> someOtherFunction;
};
Other types
Primitive types (such as int, float, const char*) or classes (std::string etc.) may be wrapped in the same way as object class do but behave differently. For example:
struct otherType {
template <class T>
otherType(T t)
: someFunction([t = std::move(t)]() {
// Return something different
return true;
})
{ }
std::function<bool()> someFunction;
};
So now it is possible to add types that does not have someFunction method.
v.emplace_back(otherType(17)); // Adding an int
v.emplace_back(otherType("test")); // A string
Solution nr. 2
After some thoughts what we basically done in first solution is created array of callable functions. So why not just do the following instead.
// Example class with method we want to put in array
struct myclass {
void draw() const {
std::cout << "myclass" << std::endl;
}
};
// All other type's behaviour
template <class T>
void draw(const T& x) {
std::cout << typeid(T).name() << ": " << x << std::endl;
}
int main()
{
myclass x;
int y = 17;
std::vector<std::function<void()>> v;
v.emplace_back(std::bind(&myclass::draw, &x));
v.emplace_back(std::bind(draw<int>, y));
for (auto& fn : v)
fn();
}
Conclusion
Solution nr. 1 is definitely an interesting method that does not require inheritance nor virtual functions. And can be used to other stuff where you need to store a template argument to be used later.
Solution nr. 2, on the other hand, is simpler, more flexible and probably a better choice here.
If you're looking at a container to store multiple types, then you should explore boost variant from the popular boost library.
Given a class with a member template function like this one:
template <typename t>
class complex
{
public:
complex(t r, t im);
template<typename u>
complex(const complex<u>&);
private:
//what would be the type of real and imaginary data members here.
}
I am confused about member template functions, please provide an example by which the need of member template functions becomes clear to me.
Also, tell me the use of member template functions in c++, what are the situations where we use member template functions?
It gives you the ability to do conversions:
complex<int> ci;
complex<float> cf(ci);
So, if you have two types T1 and T2 and you can assign a T1 to a T2, this will make it possible to assign a complex<T1> to a complex<T2>.
As for the question in your code (what would be the type of real and imaginary data members here):
template <typename t>
class complex
{
...
private:
t real_part;
t imaginary_part;
};
The most common valuable use for member template functions I come across in my day-to-day is to reduce code complexity by providing one templated function instead of many functions that do essentially the same thing.
For example, suppose you are working on a server that receives half a dozen related messages and saves the incoming data to half a dozen tables in a database. A straightforward implementation would be to implement 6 message handling functions (psudocode):
class MessageProcessor
{
void OnMessage(const char* msg);
void ProcessMessage100(Data100* data);
void ProcessMessage101(Data101* data);
void ProcessMessage102(Data102* data);
void ProcessMessage103(Data103* data);
void ProcessMessage104(Data104* data);
void ProcessMessage105(Data105* data);
};
MessageProcessor::OnMessage(const char* msg)
{
unsigned int * msgType = ((unsigned int*)msg);
switch( *msgType )
{
case 100 :
ProcessMessage100((Data100*),sg);
break;
case 101 :
ProcessMessage101((Data101*),sg);
break;
::
}
}
MessageProcessor::ProcessMessage100(Data100* data)
{
Record100* record = GetRecord100(key);
record->SetValue(xyz);
}
MessageProcessor::ProcessMessage101(Data101* data)
{
Record101* record = GetRecord101(key);
record->SetValue(xyz);
}
: :
There is an opportunity here to generalize the ProcessMessage() functions, since they do essentially the same thing:
class MessageProcessor
{
OnMessage(const char* msg);
template<class Record, class Data> void Process(Data* data);
};
template<class Record, class Data>
void MessageProcessor::Process<Record,Data>(Data* data)
{
Record* record = GetRecord(key);
record->SetValue(xyz);
}
The GetRecord function can also be generalized, yielding a codebase with 2 functions where there used to be 12. This improves the code by virtue of it being simpler with fewer moving parts, simpler to understand and maintain.
The general purpose and functionality of member function templates is in no way different from that of ordinary (non-member) function templates. The only [irrelevant] difference is that member functions have access to the implicit this parameter.
You understand the general purpose of ordinary function templates, do you? Well, in that case you should understand the general purpose of member function templates, because it is exactly the same.
Using the example you provided, the member template function allows you to construct an instance of complex<T> from complex<U>.
As a concrete example of when this might be useful, suppose you had a complex<double> but wanted a complex<float>. Without the constructor the types are unrelated so the regular copy constructor wouldn't work.
Often you would like some member function of your class to operate on a range. By having templated member functions you make it possible to operate on ranges independent of the container that supplies the range without providing an free function.
The same goes for Functors. Often you'd write a functor that operates on some sipecial pair of iterators but soon realize that it is possible to have the Functor operate on any kind of range. So instead of supplying the template parameters through the encapsulating struct you can supply them through the member function operator() and make type deduction possible.
The first examples that come to mind:
In some container constructors (or assign methods) to take input iterators of unknown type.
std::complex to allow operating on different types than the one the std::complex was instantiated from.
In shared_ptr (whether std::tr1:: or boost::) so that you can keep different types of pointers into a shared object instance in the heap (for which the pointer types can be obtained).
In thread (whether std:: in c++0x or boost::) to receive a functor of unknown type that will be called by the thread instance.
In all cases the usage is the same: you have a function that operates on types that are unknown. As AndreyT perfectly states the same that with regular functions.