I have a class with several constructors. According to a parameter which is passed via argv to main() I would like to switch between the different constructors. The following simplified example works fine in the case where "obj" is changed to class and I use e.g. obj1->int and obj2->double. But what do I have to change to make the following code run using enum?
#include<iostream>
using namespace std;
enum obj{obj1,obj2};
template <obj T>
class A
{
public:
A(T);
private:
T t_;
};
template<obj T>
A<T>::A(T )
{}
template<>
A<obj1>::A(obj1 t):t_(t) {cout<<"case 1"<< endl;}
template<>
A<obj2>::A(obj2 t):t_(t) {cout<<"case 2"<< endl;}
int main()
{
obj test=obj1;
A<obj> a(test);
return 1;
}
Thank you for your help!
EDIT: It's clear that the code is wrong concerning type/value, but which mechanism can resemble such a switching of constructors?
You have to specialize on types, not on values. If you know the value at compile-time, you could use boost::mpl::int_ to do so. If you don't (like in your case), you'll have to live with plain old if.
I think the following is what you intended to do:
#include<iostream>
enum obj{obj1,obj2};
template<obj>
class A
{
public:
A();
private:
obj t_;
};
template<obj x>
A<x>::A() : t_(x){}
template<>
A<obj1>::A() : t_(obj1){ std::cout << "obj1\n"; }
template<>
A<obj2>::A() : t_(obj2){ std::cout << "obj1\n"; }
int main()
{
const obj x = obj1; // can only be used as the template argument below because it's a compile time constant
A<x> a;
return 0;
}
However this only works if you want to 'switch' on a compile time constant, and it sounds like you don't. You need to use a run time condition (if, switch, etc).
You are approaching the problem wrong. Templates are instantiated at compile-time so you can't choose a specialization based on a value that is present at runtime. Aside from other mistakes in your code this solution won't work.
A common solution to this kind of problem (creating different objects based on a parameter) is the abstract factory pattern. It means that you move the conditional constructing logic to a factory class and use virtual methods to avoid the need to write different code on the calling side (so essentially you make use of polymorphism).
You have to do something like this:
enum E
{
A,
B
};
template<E e>
struct A
{
};
template<>
struct A<E::A>
{
};
template<>
struct A<E::B>
{
};
int main()
{
A<E::B> ab;
}
Related
I'm currently working on a piece of code in C++11:
class A {
public:
//.. generic public methods which call updateInternalState from time to time ..
private:
void updateInternalState();
B internalState;
};
Now I want to have several versions of class A which are all identical except for the updateInternalState() method, which is to vary and has atleast 3 different versions, doing different things and might have even more in the future. This sounds almost like a good place to use inheritance with a base class, but I'm wondering if there is a template-metaprogramming version for this, e.g.:
#include <functional>
template <std::function<void()> updateInternalState>
class A {
public:
//.. generic public methods, which call updateInternalState from time to time ..
private:
B internalState;
Then I would only have to define the functions somewhere else and explicitly instantiate the versions of A that I want.
I think the biggest problem is that the updateInternalState function needs access to the private members of A. I'm thinking this could be solved by declaring it as a friend of A, or by storing a member of type std::function and assigning the the template argument to it.
Does anyone have experience with such approaches and any recommendations?
Is it a terrible idea and should I just go back to inheritance (which I do not really want, since the rest of the project is written in the generic programming paradigm.)
If update function only uses internalState, you can simply store std::function<void(B&)> as a member, which is passed during construction:
class A
{
public:
template <typename F>
A(F&& func)
: updateFunc(std::forward<F>(func))
void doSomething()
{
updateFunc(internalState);
}
private:
using UpdateFunc = std::function<void(B&)>;
B internalState;
UpdateFunc updateFunc;
};
With this method, you can achieve nice flexibility while still maintaining single type instead of whole hierarchy.
Template-based solution may not be a good idea here - you only need to customize a single function, but making this a class template will cause to generate the whole class for every different function used as an argument. The only advantage is that you can specialize (or partially specialize) the logic, but it sounds like you doesn't need that.
Use inheritance or store update function as a member.
That will be a full academic answer :-)
First remark: What you want to do simply makes no sense!
Step by step:
You can use function pointers as template parameters as this:
using FUNCPTR_T = void(*)();
template < FUNCPTR_T f >
class A {
public:
void DoSomething()
{
(*f)();
}
};
void f1() { std::cout << "f1" << std::endl; }
void f2() { std::cout << "f2" << std::endl; }
int main()
{
A<f1> a1;
A<f2> a2;
a1.DoSomething();
a2.DoSomething();
}
But if you want to pass a parameter to your function, which is a class pointer ( this ), you need to define a function pointer which represents this like:
using FUNCPTR_T = void(*)(!!!POINTER_TO_THE_CLASS!!!);
But this class itself is a template which takes a pointer to a function which has a parameter which is a pointer to a class which takes a pointer to a function .... // endless recursion!
So your attempt simply fail at the point as you are unable to give a correct type for the template parameter.
And as already mentioned: Inheritance is much easier and works perfect. Using CRTP is often used to get access to the using class. Using std::function is much easier but moves the cost to runtime.
You can store a std::function and use lambdas: check out this simple class and its use as an example:
#include <functional>
#include <iostream>
#include <conio.h> // for _getch()
class A {
private:
int _state;
std::function<int()> _updater;
public:
A() : _state( 0 ) {}
void addUpdater( std::function<int()> updater ) {
_updater = updater;
}
void callUpdater() {
updateInternalState();
}
int returnState() const {
return _state;
}
private:
void updateInternalState() {
_state = _updater();
}
};
int main() {
A a;
a.addUpdater( []() { return 5; } );
a.callUpdater();
std::cout << a.returnState() << std::endl;
a.addUpdater( []() { return 10; } );
a.callUpdater();
std::cout << a.returnState() << std::endl;
_getch();
return 0;
}
Then to keep track of different instances of the same class, instead of inheritance you can use a map <id, this*> where id could be an int or a string. Makes for easy look up too. I think this might be better than templates in this situation because if you template this class where only the function differs it will generate a whole new class for each function change. Yes it does move things to runtime because of std::function, but it appears to be simpler to implement and manage.
Suppose I have a class template which have a member pData, which is an AxB array of arbitary type T.
template <class T> class X{
public:
int A;
int B;
T** pData;
X(int a,int b);
~X();
void print(); //function which prints pData to screen
};
template<class T>X<T>::X(int a, int b){ //constructor
A = a;
B = b;
pData = new T*[A];
for(int i=0;i<A;i++)
pData[i]= new T[B];
//Fill pData with something of type T
}
int main(){
//...
std::cout<<"Give the primitive type of the array"<<std::endl;
std::cin>>type;
if(type=="int"){
X<int> XArray(a,b);
} else if(type=="char"){
X<char> Xarray(a,b);
} else {
std::cout<<"Not a valid primitive type!";
} // can be many more if statements.
Xarray.print() //this doesn't work, as Xarray is out of scope.
}
As the instance Xarray is constructed inside of an if statement, I cannot use it anywhere else. I tried to make a pointer before the if statements but as the type of the pointer is unknown at that point, I did not succeed.
What would be a proper way of dealing with this kind of a problem?
The problem here is that X<int> and x<char> are completely unrelated types.
The fact that they are both a result of the same templated class won't help here.
I can see several solutions, but those depends on what you really need.
You could, for instance make the X<> instances derive from a common non-templated base class that has the print() method (eventually as a pure virtual). But before you do that, be sure that it makes sense on a functional level: one should use inheritance because it makes sense, not solely because of technical constraints. And if you do that, you probably will want to have a virtual destructor as well.
You could also bind and store a std::function<void ()> to the method you want to call, but ensure that the objects are still "alive" (they aren't in your current code: both the X<int> and X<char> are destroyed when they go out of scope, way before you actually call print()).
A final solution would be to make some variant type that is compatible with both X<int> and X<char> (boost::variant<> can help here). You could then write a visitor that implements the print() functionality for each type.
Picking the last solution, it would become something like:
typedef boost::variant<X<int>, X<char>> genericX;
class print_visitor : public boost::static_visitor<void>
{
public:
template <typename SomeType>
void operator()(const SomeType& x) const
{
// Your print implementation
// x is your underlying instance, either X<char> or X<int>.
// You may also make several non-templated overloads of
// this operator if you want to provide different implementations.
}
};
int main()
{
boost::optional<genericX> my_x;
if (type=="int") {
my_x = X<int>(a,b);
} else if(type=="char") {
my_x = X<char>(a,b);
}
// This calls the appropriate print.
if (my_x) {
boost::apply_visitor(print_visitor(), *my_x)
}
}
We actually lack the knowledge to give a definitive answer: if your classes are "entities", then you probably should go for inheritance. If they are more like "value classes", then the variant way might be more suited.
C++ is a statically typed language, meaning that you must know the type of objects at compile time. In this case you are basing the type of the object constructed on user input, so it's not possible to know the type at runtime.
The most common way to address this issue is to use dynamic polymorphism in which functions are invoked via a common interface using late binding. We accomplish this in C++ using virtual functions. For example:
struct IPrintable {
virtual void print() = 0;
};
template<class T>
class X : public IPrintable {
// Same code as you showed above.
};
int main() {
std::cout<<"Give the primitive type of the array"<<std::endl;
std::cin>>type;
std::unique_ptr<IPrintable> XArray;
if(type=="int"){
XArray.reset(new X<int>(a,b));
} else if(type=="char"){
XArray.reset(new X<char>(a,b));
} else {
std::cout<<"Not a valid primitive type!";
} // can be many more if statements.
Xarray->print() // this works now!
}
This solves the out of scope issue and allows you to print using the dynamic type of the XArray variable. Virtual functions are the secret sauce that make this possible.
Rather than trying to fit the templates into main I would go the opposite way than the rest of the suggestions... move the code out of main and into it's own (possibly templated) function that needs to deal with a single type:
template <typename T>
void generateAndPrint(int a, int b) {
X<T> x(a,b);
x.print();
}
int main() { ...
if (type=="int") generateAndPrint<int>(a,b);
else if (type=="char") generateAndPrint<char>(a,b);
else ...
}
If you want to work with different arrays, whatever their type, templates alone cannot help you. Currently, there is exactly no relationship between X<int> and X<char>.
If you want to treat them as two subtypes of a common type, you will have to use inheritance (and dynamically allocated variables). For instance, all X<T> may inherit the same base class, say Printable, and you can store the data in a unique_ptr<Printable>:
unique_ptr<Printable> r;
if(type=="int"){
r.reset(new X<int>(a,b));
} else if(type=="char"){
r.reset(new X<char>(a,b);
}
r->print();
But this is probably not the best design.
A probably better solution would be, instead of trying to work outside of the if, to move all the work inside of the if. In your simple example, this could be done by duplicating the call to print, but this is not pretty nice either. But, going toward this idea, we can create a template function that does the job:
template<class T>
void workWithType(int a, int b)
{
X<T> Xarray(a, b);
Xarray.print();
}
//...
if(type=="int"){
workWithType<int>(a,b);
} else if(type=="char"){
workWithType<char>(a,b);
}
Consider this code
enum Types
{
t1,
t2
};
struct Base
{
Types typeTag;
Base(Types t) : typeTag(t){}
};
template<typename T>
struct Derived : Base
{
using Base::Base;
T makeT() { return T(); }
};
int main()
{
Base *b = new Derived<std::string>(t1);
auto d = getDerivedByTag(b); // How ??
d->makeT();
return 0;
}
Is it possible to restore Derived type parameter by Base::typeTag value in runtime? Obviously, some external preliminarily prepared mapping is needed, but I can't figure out the exact way.
What you want is basically a reflection that is not (yet) supported in C++. There are ways to simulate it or work around it but they are often verbose and not elegant. I would suggest rethinking your design, particularly your use of auto. It is not supposed to substitute for "any type" as you seem to imply by your code. It is meant as simplification of code when actual type is long or obfuscated (often happens with templates), nested etc. Not when you do not know the type! Because then you cannot really use it, can you.
So what you will have to do in one way or another is check the typeTag directly and continue based on that information. Alternatively you would need to use polymorphism using the Base directly (calling virtual methods propagated to Derived). For type unions you could use boost::variant (if you do not care what type Derived template argument is) or some other framework/library alternative like QVariant in Qt.
I'm not sure if my understanding is correct.
#include "iostream"
enum Types
{
t1,
t2
};
template<typename T>
struct Base
{
typedef T DerivedType;
Types typeTag;
Base(Types t) : typeTag(t){}
DerivedType* operator()() {
return static_cast<DerivedType*>(this);
}
};
template<typename T>
struct Derived : Base<Derived<T>>
{
Derived(Types t): Base<Derived<T>>(t) {}
T makeT() { return T(); }
};
int main()
{
Base<Derived<std::string>> *b = new Derived<std::string>(t1);
auto d = (*b)();
d->makeT();
return 0;
}
https://godbolt.org/g/uBsFD8
My implementation has nothing to do with typeTag.
Do you mean getDerivedByTag(b->typeTag) rather than getDerivedByTag(b)?
Suppose I have a class template which have a member pData, which is an AxB array of arbitary type T.
template <class T> class X{
public:
int A;
int B;
T** pData;
X(int a,int b);
~X();
void print(); //function which prints pData to screen
};
template<class T>X<T>::X(int a, int b){ //constructor
A = a;
B = b;
pData = new T*[A];
for(int i=0;i<A;i++)
pData[i]= new T[B];
//Fill pData with something of type T
}
int main(){
//...
std::cout<<"Give the primitive type of the array"<<std::endl;
std::cin>>type;
if(type=="int"){
X<int> XArray(a,b);
} else if(type=="char"){
X<char> Xarray(a,b);
} else {
std::cout<<"Not a valid primitive type!";
} // can be many more if statements.
Xarray.print() //this doesn't work, as Xarray is out of scope.
}
As the instance Xarray is constructed inside of an if statement, I cannot use it anywhere else. I tried to make a pointer before the if statements but as the type of the pointer is unknown at that point, I did not succeed.
What would be a proper way of dealing with this kind of a problem?
The problem here is that X<int> and x<char> are completely unrelated types.
The fact that they are both a result of the same templated class won't help here.
I can see several solutions, but those depends on what you really need.
You could, for instance make the X<> instances derive from a common non-templated base class that has the print() method (eventually as a pure virtual). But before you do that, be sure that it makes sense on a functional level: one should use inheritance because it makes sense, not solely because of technical constraints. And if you do that, you probably will want to have a virtual destructor as well.
You could also bind and store a std::function<void ()> to the method you want to call, but ensure that the objects are still "alive" (they aren't in your current code: both the X<int> and X<char> are destroyed when they go out of scope, way before you actually call print()).
A final solution would be to make some variant type that is compatible with both X<int> and X<char> (boost::variant<> can help here). You could then write a visitor that implements the print() functionality for each type.
Picking the last solution, it would become something like:
typedef boost::variant<X<int>, X<char>> genericX;
class print_visitor : public boost::static_visitor<void>
{
public:
template <typename SomeType>
void operator()(const SomeType& x) const
{
// Your print implementation
// x is your underlying instance, either X<char> or X<int>.
// You may also make several non-templated overloads of
// this operator if you want to provide different implementations.
}
};
int main()
{
boost::optional<genericX> my_x;
if (type=="int") {
my_x = X<int>(a,b);
} else if(type=="char") {
my_x = X<char>(a,b);
}
// This calls the appropriate print.
if (my_x) {
boost::apply_visitor(print_visitor(), *my_x)
}
}
We actually lack the knowledge to give a definitive answer: if your classes are "entities", then you probably should go for inheritance. If they are more like "value classes", then the variant way might be more suited.
C++ is a statically typed language, meaning that you must know the type of objects at compile time. In this case you are basing the type of the object constructed on user input, so it's not possible to know the type at runtime.
The most common way to address this issue is to use dynamic polymorphism in which functions are invoked via a common interface using late binding. We accomplish this in C++ using virtual functions. For example:
struct IPrintable {
virtual void print() = 0;
};
template<class T>
class X : public IPrintable {
// Same code as you showed above.
};
int main() {
std::cout<<"Give the primitive type of the array"<<std::endl;
std::cin>>type;
std::unique_ptr<IPrintable> XArray;
if(type=="int"){
XArray.reset(new X<int>(a,b));
} else if(type=="char"){
XArray.reset(new X<char>(a,b));
} else {
std::cout<<"Not a valid primitive type!";
} // can be many more if statements.
Xarray->print() // this works now!
}
This solves the out of scope issue and allows you to print using the dynamic type of the XArray variable. Virtual functions are the secret sauce that make this possible.
Rather than trying to fit the templates into main I would go the opposite way than the rest of the suggestions... move the code out of main and into it's own (possibly templated) function that needs to deal with a single type:
template <typename T>
void generateAndPrint(int a, int b) {
X<T> x(a,b);
x.print();
}
int main() { ...
if (type=="int") generateAndPrint<int>(a,b);
else if (type=="char") generateAndPrint<char>(a,b);
else ...
}
If you want to work with different arrays, whatever their type, templates alone cannot help you. Currently, there is exactly no relationship between X<int> and X<char>.
If you want to treat them as two subtypes of a common type, you will have to use inheritance (and dynamically allocated variables). For instance, all X<T> may inherit the same base class, say Printable, and you can store the data in a unique_ptr<Printable>:
unique_ptr<Printable> r;
if(type=="int"){
r.reset(new X<int>(a,b));
} else if(type=="char"){
r.reset(new X<char>(a,b);
}
r->print();
But this is probably not the best design.
A probably better solution would be, instead of trying to work outside of the if, to move all the work inside of the if. In your simple example, this could be done by duplicating the call to print, but this is not pretty nice either. But, going toward this idea, we can create a template function that does the job:
template<class T>
void workWithType(int a, int b)
{
X<T> Xarray(a, b);
Xarray.print();
}
//...
if(type=="int"){
workWithType<int>(a,b);
} else if(type=="char"){
workWithType<char>(a,b);
}
I'm not exactly sure how to word this in English, but I want to do something like this:
template <class T>
class derived: public T
{ blah };
Where basically, I have a template class, but I'm deriving a new class from the class that is specified in the template? I.e. so I wouldn't necessarily know the class at compile time.
Is this even possible? If so, What are the semantics for this?
For example, say I'm trying to write a "parent" class. For the purposes of this example, let's say it's a tree parent. The tree parent, is a tree itself (so it inherits from tree), but also has a vector of references to child trees.However, the parent class itself doesn't have to be a tree; it could be any class, such that I could write something like:
Parent<tree> treeParent;
Parent<shrub> shrubParent;
Yes. That is possible. Try doing that.
I wouldn't necessarily know the class at compile time.
I think, you mean "I wouldn't necessarily know the class at the time of defining the class template."
By the time you compile, you've already defined the class template, and used it in your code, passing template argument to it, which means you know the class (i.e template argument) at compile time. If you don't know the class to be used as base, then you cannot even compile the code.
This is indeed possible and commonly used for policy based design:
Like in this incredibly contrived example:
template<typename OutputPolicy>
struct Writer : public OutputPolicy {
using OutputPolicy::print;
void write(const std::string&) {
//do some formatting etc.
print(string);
}
};
class StdoutPolicy {
public:
set_linebreaks(const std::string&);
protected:
void print(const std::string&);
};
The public method in the policy will be accessible through Writer. That way a policy can decorate the class it is used in with additional methods.
Yes this is possible. The semantic for this is no different from the semantic for any other use of a template parameter in the class template. You can have a member of type T, a function parameter of type T, and you can have T as a base class too. It's not special.
Like this:
#include <iostream>
using namespace std;
template<typename T>class classTemplateBase
{
public:
T value;
classTemplateBase(T i)
{
this->value = i;
}
void test()
{
cout << value << endl;
}
};
class classTemplateChild : public classTemplateBase<char>
{
public:
classTemplateChild( ): classTemplateBase<char>( 0 ) // default char is NUL
{
;
}
classTemplateChild(char c): classTemplateBase<char>( c )
{
;
}
void test2()
{
test();
}
};
int main()
{
classTemplateBase <int> a( 42 );
classTemplateChild b( 'A' );
a.test(); // should print "42"
b.test(); // should print "A"
b.test2(); // should print "A"
return 0;
}
This is possible an it is also very common and has gotten it's own name: the Curiously recurring template pattern. See the Wikipeida entry on Curiously recurring template pattern.