creating a generic instance of a class template in c++ - c++

I'm making a template library in c++. I think it needs to be in the form of a template class because it has to be able to store some data. I would like to be able to create an instance of that class without having to specify a data type.
Here's what the class template would look like
template<class T>
class MyTemplateClass{
public:
void saveData(T data);
private:
T my_data;
};
template<class T>
void MyTemplateClass<T>::saveData(T data){
//bunch of code goes here
}
and here's how I would like to declare it:
class LibraryUser{
public:
void saveDoubleData(double data);
void saveFloatData(float data);
private:
MyTemplateClass<UNKNOWN_TYPE> my_generic_object;
};
and use it:
void LibraryUser::saveDoubleData(double data){
my_generic_object.saveData(data);
}
void LibraryUser::saveFloatData(float data){
my_generic_object.saveData(data);
}
What should UNKNOWN_TYPE be? Is this possible?
EXTRA NOTES: I cannot edit the function prototypes of the LibraryUser class because it is part of an existing plug-in framework. I'd rather not use template specialization because I don't want to double the code in saveData() since it's actually pretty long.

You should make the LibraryUser class a template as well:
template<class T>
class LibraryUser{
public:
void saveData(T data);
private:
MyTemplateClass<T> my_generic_object;
};
Alternatively, you can use boost::any if the type is really unknown, or boost::variant if the type is in a specified set of types.

The template classes are actually different from each other so you can't really change the template type runtime without using some trick. If you don't want to make LibraryUser also a template, you can store multiple variables. In this case, if you want to save yourself the trouble of duplicating every code, but you have a limited number of different types just use multiple variables and store which one is actually used. Not really nice, but saves you from making more template classes.
class LibraryUser{
public:
void saveIntData(int data);
void saveFloatData(float data);
private:
MyTemplateClass<int> my_int;
MyTemplateClass<float> my_float;
};
Use it:
void LibraryUser::saveFloatData(float data){
my_float.saveData(data);
}
void LibraryUser::saveIntData(int data){
my_int.saveData(data);
}

Instead of having a class member, why not use local instances of your template class?
void LibraryUser::saveIntData(float data){
MyTemplateClass<float> saver;
saver.saveData(data);
}
void LibraryUser::saveFloatData(int data){
MyTemplateClass<int> saver;
saver.saveData(data);
}
If MyTemplateClass needs s.th. you want to have initialized once (e.g. a database connection), make a class member for that one separately (in LibraryUser) and pass a reference to the constructor of MyTemplateClass:
template<class T>
class MyTemplateClass{
public:
MyTemplateClass(DBConnection& conn);
void saveData(T data);
private:
T my_data;
DBConnection& my_conn;
};
class LibraryUser{
public:
void saveIntData(int data);
void saveFloatData(float data);
private:
DBConnection my_conn;
};
void LibraryUser::saveIntData(float data){
MyTemplateClass<float> saver(my_conn);
saver.saveData(data);
}
About your EXTRA NOTES:
It is also safe to assume that a given OtherClass object will consistently only call either saveFloatData or saveIntData, not both.
IMHO that's a bad assumption (restriction) made for client usage, if you're going to design a framework.
UPDATE:
Another option I can think of, is to just templating the function in question, not the whole class:
class MyGenericClass{
public:
MyGenericClass();
template<class T>
void saveData(T data);
};

Related

Create a templated variable within a templated class of a different type

I'm not sure what I am asking for is possible.
I have a templated class called Controller. This is a variadic template class which takes multiple classes and can set their values as such.
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
This takes a bunch of different classes together and allows me to to set their values at the same time. setValues is a templated function which allows any type to be passed in. However, right now I am trying to modify my class so that I can set a value within the controller itself for easy retrieval. However this is the part that is proving difficult.
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
private:
std::tuple<Classes&...> objects;
};
I want to add the following as a private variable T controllerValue; However, I know that I cannot simply declare T because we cannot define member templates and the compiler has no idea what to expect. Which then I tried to create a private struct:
template<typename T>
struct ControllerValue { T value; };
However, I cannot define a struct underneath that, because the same problem occurs. The compiler has no idea what type ControllerValue is. What I would like is something like this:
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
thisValue.value = value;
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
template<typename T>
T getValue() const { return thisValue.value }
private:
std::tuple<Classes&...> objects;
template<typename T>
struct ControllerValue { T value; };
ControllerValue thisValue;
};
This will not compile at all for the same reason that the compiler has no idea what type ControllerValue should be. And this is where I am stuck. Is this even possible to do? If not, what is another way that I can make this work?
To clear up confusion, the use case would be something like this:
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
int commonValue = myController->getValue();
or
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32.3);
double commonValue = myController->getValue();
I think solving this exact problem is impossible in C++ (and still very cumbersome in languages with runtime generics). You can very easily create a polymorphic class that can only store any value:
class PolymorphicBase
{
public:
virtual ~PolymorphicBase() = default;
};
template <class T>
class PolymorphicObject : public PolymorphicBase
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
};
A member of std::unique_ptr<PolymorphicBase> can sufficiently store any value, but how would such a value be retrieved? Probably the easiest is to expose the reference to PolymorphicBase and use dynamic type checks to see if the type is compatible with something you know, but what if you need the code to work for any type?
This is what lambdas with auto parameters are useful for. However, you would have to be able to pass such a lambda to a method on PolymorphicBase and implement that method in PolymorphicObject. This is impossible, since you cannot override a method template (it needs to be a template to accept a lambda) – that's where the compile-time and runtime parts of C++ clash. And there is simply no type in C++ that represents a function accepting any parameter (and knowing its type), which is a template by itself.
You can partially solve this by making the type of the lambda known to PolymorphicBase:
template <class Retriever>
class PolymorphicBase
{
public:
virtual void retrieve(Retriever func) = 0;
virtual ~PolymorphicBase() = default;
};
template <class Retriever, class T>
class PolymorphicObject : public PolymorphicBase<Retriever>
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
void retrieve(Retriever func) override
{
func(value);
}
};
auto lambda = [](auto arg)
{
std::cout << arg << std::endl;
};
PolymorphicObject<decltype(lambda), int> obj(6);
PolymorphicBase<decltype(lambda)> &ptr = obj;
ptr.retrieve(lambda);
This is useful if you ever have only a single way to retrieve the value.
I don't think this is needed in most cases anyway. Usually you use a fixed set of types as the values, so you can use a variant there, or they all implement a common interface, or (as you've pointed out in the comments) you actually meant to move the type parameter from the method to the class (which allows you to check that all the types actually support the value earlier than originally).
However, I agree that in languages with generics/templates it is somewhat hard to have a method that can actually choose its result type in a generic fashion, without being controlled by outside parameters.

How to use a template of a template of 2 classes which one is hereditary of the other class

How can you use a template of a template? Following problem is given:
You have two classes (just a simple overview to show my point) :
class one
{
private:
int data;
public:
one();
int getData();
void setData(int s);
}
class two: public one
{
private:
one * current;
public:
two();
one * function1();
one * function2(one * s);
void add(int d);
void add(int d, one * s);
}
now I would do Template1 (of class one) this way:
template <class T>
class one
{
private:
T data;
public:
one();
T getData();
void setData(T s);
}
In one function of class two I have to create a object of class one. Now I'm not sure how to create template of class two. My idea was:
template <class T1, class T2>
class two: public one
{
private:
T2 current;
public:
two();
T2 function1();
T2 function2(T2);
void add(T1 d);
void add(T1 d, T2 s);
}
But then If I have to create for example in function1() an object of class one I have to create it like:
one<int> s = new one;
My Problem is I will not use a static type so I would try this:
one<T1> s = new one;
Hope you can give me a correct form of the use of templates in my classes!
Class two only needs a single template parameter:
template <class T>
class two: public one<T>
{
private:
one<T>* current;
public:
two();
one<T>* function1();
one<T>* function2(one<T>*);
void add(T d);
void add(T d, one<T>* s);
};
live example: https://ideone.com/nrTK6C
Well the correct syntax would just involve using one<T>:
template <class T>
class two: public one<T>
{
private:
one<T>* current;
public:
two();
one<T>* function1();
one<T>* function2(one<T>*);
void add(T d);
void add(T d, one<T>* s);
}
It seems a little odd to both derive from a class and hold a pointer to the an object of the same class, but I'll assume you have a reasonable use-case.
That operation is not possible.
Firstly, your class two must specify one's template parameters when deriving from it.
Secondly, you cannot use inheritance to dodge the fact that C++ is a statically typed language. You must know all the types of the type that you are using. If one is a template, you must specify the template parameter for it to be a complete type that you can actually use. You cannot simply wish the parameter away.
You have only two choices. Specify a subset of one's interface that does not depend on the parameter, have one inherit from that, and then use that. Alternatively, you could simply pass in the appropriate parameter to the user of one.

How do I change a class to a template class?

I need to change the first line to : template <class T> class Node{
class Node {
private:
double data;
Node* next;
public:
Node(double);
virtual ~Node(); //for later use of polymorphismi, review the topic again
friend class Stack; // allows dStack for private member access
};
Node::Node(double data) {
this->data = data;
next = 0;
}
Node::~Node() {
}
but i am unsure of all the internal work i need to change. Do i just need to change the private data member and the public Node function?
I think what you are looking for is something along the lines of the following:
template<typename T>
class Node
{
private:
T data;
Node* next;
public:
Node(const T& d);
virtual ~Node();
// ... etc
};
Note that you will either need to implement the template class inline, in the same file, or include the implementation at the bottom of the header file.
The point is that you change your class so that it can be used for other types except double, for example int, float etc in the same way. If we think of it in more abstractly, you need to use the class for objects of type T, where T can be any of the types mentioned above (or even more).
So, in general, you need to put template <class T> (Setting it as a template class) before your class and replace double with T type.
for class declaration:
template<typename T>
class Node
for class functions implementation:
template<typename T>
Node<T>::Node()

C++ Virtual template method

I have an abstract class (I know that it will not compile this way, but it's for comprehension of what I want to do) :
class AbstractComputation {
public:
template <class T> virtual void setData(std::string id, T data);
template <class T> virtual T getData(std::string id);
};
class Computation : public AbstractComputation {
public:
template <class T> void setData(std::string id, T data);
template <class T> T getData(std::string id, T data);
};
So when I call setData<double>("foodouble", data) I want the double identified by foodouble (internal mechanism which is not the main concern here) to be set to the double data.
So how to do that?
I think that there may be a mean by typing something like virtual void setData<double>(std::string id, double data) but I don't know how to do it.
The problem is that you cannot mix static time polymorphism (templates) with runtime polymorphism easily. The reason for the language disallowing the particular construct in your example is that there are potentially infinite different types that could be instantiating your template member function, and that in turn means that the compiler would have to generate code to dynamically dispatch those many types, which is infeasible.
There are different things that can be done here to get around the limitation, basically either take away the static or the dynamic polymorphism. Removing dynamic polymorphism from the equation could be done by providing a type that is not derived from, to store the <key,value> mappings, and then offering the template that resolves that only at the base level:
class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
m_store.setData( id, value );
}
template <typename T>
T getData( std::string const & id ) const {
return m_store.getData<T>( id );
}
protected:
ValueStore m_store;
};
Now deriving classes can access the ValueStore from the base and there is no need for polymorphism. (This can also be done by implementing the functionality directly in AbstractComputation but it probably makes sense to separate concerns)
The other option is to maintain runtime polymorphism, but remove static polymorphism. This can be done by performing type erasure on the base class and then dispatching to the appropriate (non-templated) function that takes the type-erased arguments. The simplest version of this is just using boost::any:
class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
setDataImpl( id, boost::any( value ) );
}
template <typename T>
T getData( std::string const & id ) const {
boost::any res = getDataImpl( id );
return boost::any_cast<T>( res );
}
protected:
virtual void setDataImpl( std::string const & id, boost::any const & value ) = 0;
virtual boost::any getDataImpl( std::string const & id ) const = 0;
};
How type erasure is implemented under the hood is interesting, but out of the scope here, the important part is that a boost::any is a concrete (non-templated) type that can store any type internally by using type erasure on the arguments, and at the same time allows for type-safe retrieval of the data.
In some cases it may be enough to move the templating from method level to class level, e.g.:
#include <iostream>
template<typename T>
class AbstractComputation {
public:
virtual void setData(std::string id, T data)
{
std::cout << "base" << std::endl;
}
};
template<typename T>
class Computation : public AbstractComputation<T> {
public:
virtual void setData(std::string id, T data)
{
std::cout << "derived" << std::endl;
}
};
int main()
{
AbstractComputation<int> *x = new Computation<int>();
x->setData("1", -1);
delete x;
return 0;
}
You can probably use boost::any in your case.
virtual void setData(std::string id, boost::any data);
It is a wrapper that can encapsulate almost anything.
More info on a similar topic in this answer.
First, you cannot have virtual template functions. As templates are resolved at compile time, virtual will not work, as the compiler would not know which template to pick. See here, for more info about this.
If you know list of possible types in advance, preprocessor may help:
#define MY_CLASSES MYTYPE(int) MYTYPE(float) MYTYPE(double)
class AbstractComputation {
public:
# define MYTYPE(T) virtual void setData(std::string id, T data)=0;\
virtual void getData(std::string id, T& dst_data)=0;
MY_CLASSES
# undef MYTYPE
};
class Computation : public AbstractComputation {
public:
# define MYTYPE(T) virtual void setData(std::string id, T data){std::cout<<"writing: "<<data<<std::endl;}\
virtual void getData(std::string id, T& dst_data){dst_data=0;/*put your actual implementation here*/}
MY_CLASSES
# undef MYTYPE
};
If you don't know a complete list of possible types, perhaps, your problem is unresolvable. Type erasure, as mentioned by others, may also help.. but not in all circumstances.
Use boost::any to accept the datum, and then when you actually set, grab the correct type from it.

How to code inlineable mutual abstracion in C++?

Example first:
template <class HashingSolution>
struct State : public HashingSolution {
void Update(int idx, int val) {
UpdateHash(idx, val);
}
int GetState(int idx) {
return ...;
}
};
struct DummyHashingSolution {
void UpdateHash(int idx, int val) {}
void RecalcHash() {}
};
struct MyHashingSolution {
void UpdateHash(int idx, int val) {
...
}
void RecalcHash() {
...
UpdateHash(idx, GetState(idx)); // Problem: no acces to GetState function, can't do recursive application of templates
...
}
};
In this example I can pass MyHashingSolution to State class so State have access to HashingSolution's methods, but HashingSolution can't call GetState. Is it possible to work around this?
This is in the deepest loop. virtual function here drops the performance by more than 25%.
Inlineing is crucial for me.
As jalf suggests in the comments, you probably want to use a variant of the Curiously Recurring Template Pattern (CRTP). That is, make MyHashingSolution a class template parametrised by the derived class:
template <typename D>
struct MyHashingSolution {
typedef D Derived;
void UpdateHash(int idx, int val) {
...
}
void RecalcHash() {
...
UpdateHash(idx, derived().GetState(idx));
...
}
private:
// Just for convenience
Derived& derived() { return *static_cast<Derived*>(this); }
};
In this case, because you want the derived State class to also be a template, you need to take the slightly unusual step of declaring State as a class template that takes a template template parameter:
template <template <class T> class HashingSolution>
struct State : public HashingSolution<State<HashingSolution> > {
typedef HashingSolution<State<HashingSolution> > Parent;
void Update(int idx, int val) {
Parent::UpdateHash(idx, val); // g++ requires "Parent::"
}
int GetState(int idx) {
return ...;
}
};
The key point is that, provided State inherits from HashingSolution<State<HashingSolution> >, Derived is a derived class of HashingSolution<State<HashingSolution> > so the static_cast<Derived*>(this) downcast in HashingSolution<State>::derived() compiles and works correctly. (If you mess up and derive State from HashingSolution<SomeOtherType> instead and then try something that involves a call to derived(), the compiler will complain as the requirements for static_cast<> are not met.)
Then declare the concrete State class you want to use like so:
typedef State<MyHashingSolution> MyState;
Unfortunately this solution has the side effect that you will need to change DummyHashingSolution (and any other such types) to templates that ignore their one template argument, in order to make them usable as template template arguments.
As a shot in the dark, considering the almost complete lack of information in the question (see comments): would templates be useful? They're often good for compile-time polymorphism.
To get any more potentially useful information, please explain the problem more. Look at the problem comments. Tell us why you know what micro-optimizations need to be made when you're still working on fundamental design. If there's anything non-mainstream about the compilation or execution environments, give us a few details.