Something like:
template<bool HOLD_MANUFACTURER>
class Computer {
int memory;
int storage;
#if HOLD_MANUFACTURER
char *manufacturer;
#endif
};
I need this to create two variations of the almost-same class, when one variation is a lighter one for performance reasons. I don't want to use a separate class that will wrap the lighter one.
If yes, is it possible to any type (not just bool from the sample code above)? Maybe primitive types only? What about enums?
This code don't work for me, but I hope that I've just missed some little thing.
You can creatively use the empty base optimization in a policy approach to achieve almost what you want:
struct NO_MANUFACTURER {};
struct HOLD_MANUFACTURER { char *manufacturer; };
template <typename ManufacturerPolicy>
class Computer : public ManufacturerPolicy
{
int memory;
int storage;
}
Then instantiate as Computer<HOLD_MANUFACTURER> computer_with_manufacturer;
Not possible, but you can use template specialization and inheritance:
template <bool HoldManufacturer>
class ComputerAdditions
{};
template <>
class ComputerAdditions<true>
{
protected:
char *manufacturer;
public:
// Methods using this additional member
};
template <bool HoldManufacturer = false>
class Computer
: public ComputerAdditions<HoldManufacturer>
{
int memory;
int storage;
public:
// Methods of Computer
}
Related
I want to declare member variables in a class template if some condition from template parameters is true. I could use nested class as container, but it is impossible to do explicite specializations in that case.
I'm trying someting like this:
enum class VarPolice { Declare, DontDeclare };
template<VarPolice vp = VarPolice::Declare>
class MyClass
{
struct EmptyStruct {};
struct VarSaverStruct { int MyVar; };
using VarSaver = typename std::conditional<vp == VarPolice::Declare, VarSaverStruct, EmptyStruct>::type;
VarSaver saver;
}
So, I can use MyVar as saver.MyVar
Is there any way to do optional variable declaration without using EmptyStruct that has a size overhead?
C++17 can be used.
Yes, you can have your cake and eat it too. Just inherit from correct type instead, and rely on the empty base optimization.
enum class VarPolice { Declare, DontDeclare };
struct EmptyStruct {};
struct VarSaverStruct { int MyVar; };
template<VarPolice vp = VarPolice::Declare>
class MyClass : std::conditional_t<vp == VarPolice::Declare,
VarSaverStruct, EmptyStruct>
{
};
Standard library implementations rely on it themselves to "store" allocators without taking up space if they are stateless.
I have a socket data type class that is used to read and parse a value from socket stream (may be used for file too).
Let my class be mc_double:
class mc_double {
private:
double value;
public:
bool read(socket);
write(double);
}
Actual class is more complicated, but this is the principle. Now, I need to parse float from the stream. Float is way similar to double, so is already implemented int. Could't I merge this class definitions, with all double, int and float somehow templated?
This is what I mean:
class mc_<typename = double or int or float> {
private:
typename value;
public:
bool read(socket);
write(typename);
}
Some methods would be then defined individualy as mc_double::method() others would be same for all types: mc_typename::general_method(). Also, for some I'd need just minor changes in code:
typename mc_typename::return_value() {
return val;
}
Or the constructor:
mc_typename::mc_typename(<int, long, char, double> number) {
val = (typename)number;
}
The result should be three classes - mc_int, mc_float and mc_double.
I have found the official C++ template docs, but I only figured out the last part of my question - I can create a function that accepts multiple data types. The rest does not seem to be that easy.
You could make your class a class template:
template<typename T, bool base = true>
class mc {
protected:
T value;
public:
bool read(socket);
write(T);
};
This class will contain the member function that are common for all types T. Then, you could specialize this class templates separately for different types and let them inherit from mc<T, true>:
template<>
class mc<double, true> : public mc<double, false> {
public:
// Member functions for double only...
};
template<>
class mc<int, true> : public mc<int, false> {
public:
// Member functions for int only...
};
Make sure the non-public member data of the primary class template are made protected if you want derived classes to access them.
You could then instantiate them this way:
mc<double> m;
mc<int> m;
// ...
If you really want to use the mc_double and mc_int names, then you could either:
a) Create type aliases for them:
typedef mc<double> mc_double;
typedef mc<int> mc_int;
b) Change the design of the class template to not use specialization and have one single template parameter, and create the derived classes independently:
template<typename T>
class mc {
protected:
T value;
public:
bool read(socket);
write(T);
};
class mc_double : public mc<double> {
public:
// Member functions for double only...
};
class mc_int: public mc<int> {
public:
// Member functions for int only...
};
You could use templates in the class definition as follows:
template <typename T>
class mc
{
public:
bool write(T _val);
private:
T mVal;
};
but you can't as easily specialize some methods but not others based on the type of T (i.e., you have to specialize the entire class, not just one method). You could solve this with some sort of inheritance hierarchy, where methods that are the same regardless of the type are in the base, and the specialization is in derived classes. So keep the above (assuming write is one that doesn't change) and create:
class mc_double : public mc<double>
{
public:
void doSomethingSpecific() { /* code specific for 'doubles' */ }
};
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;
}
I'm currently writing a class which allows getting and setting interal program options and it should be quite flexible and easy to use.
Specifically, an option is identified by an enum type and a value type, which have a one-on-one relationship. For example, an enum IntType will contains options which have an int type.
I had in mind the following code, but have no idea how to get it working or whether I'm trying to use templates in a way i shouldn't.
enum IntType {OPTION1, OPTION2}
enum StringType { OPTION3, OPTION4}
template<class T, class T2>
class Policy{
public:
T2 getValue(const T& a);
void setValue(const std::string& name, const T2& a);
...
}
class A: public Policy<IntType, int>, public Policy<Stringtype, std::string>, ...{
...
}
Each enum constant has one associated string representation, which is constant, but options are also taken as string input into the program, so I have to be able to deduce from a string which option I should change.
But obviously, this code cannot be used to directly call set or get values without qualifying its full template specialization. So
A* a = ...
a->setValue("intoption", 5);
will not work.
Any pointers on what I should use to get this working?
A partial answer on how to derive at compile time that OPTION1 maps to int and IntType, ... would also be great.
Thanks in advance,
Broes
It is not necessary to pass both the Enum and the type. You can deduce the enum value from the type itself thanks to a traits class:
template <typename T>
struct PolicyTraits;
template <>
struct PolicyTraits<int> { static Enum const value = IntType; }
// ... and so on ...
Your selection is obviously a bit more difficult. For templates to work correctly you need selection based on compile constants, be they constants or types. This requires the names of your options to be constants.
A revised implementation would thus be:
template<class Name, class Type>
class Policy{
public:
Type getValue(Name);
void setValue(Name, Type const&);
...
}
This can be used as:
struct IntOption {};
class A: public Policy<IntOption, int> {};
int main() {
A a;
a.setValue(IntOption(), 3);
}
Also, you might be interested in looking up How Boost does it and perhaps use their library.
Since you are filling the data at runtime, templates are not viable for this design. Runtime polymorphism with virtual function will be a good choice. For example,
class Options; // Say this is the class of interest
class DataType {
public:
virtual Options& getOptions () = 0;
};
class IntType : public DataType {
public:
Options& getOptions (); // implement for 'int' type
};
class StringType : public DataType {
public:
Options& getOptions (); // implement for 'std::string' type
};
Now, class A should contain a pointer to DataType;
class A {
DataType *pData;
public:
void setValue (DataType *p) { pData = p; }
...
};
Usage:
A *a = ...;
a->setValue(new IntType); // take care of heap allocation / stack allocation
My container needs to store a little information about its elements. Normally, I store this separately from elements. However, I'd like to give users possibility to conserve memory by dedicating a field in element structure type for external use. E.g.:
struct MyStuff
{
int foo;
char bar;
mutable char dedicated_for_external_use; // Because of alignment, this field
// won't increase sizeof (MyStuff)
};
The idea here is that the field must not be accessed by anything but element's container. Since containers store a copy (much like std::vector), it wouldn't be a problem if you added any given value x to several containers.
How would you design an interface for this that, if possible, would meet the following requirements?
Should be completely optional. I.e. it should be possible to automatically determine if given type provides such a field or not and then container would only use it if available.
Ideally, wouldn't depend on type traits etc. as I need maximum compiler compatibility.
Should be easy to use. I.e. if you can and want to enable this optimization for type MyStuff, you could do it with 3 lines of code, not 25. Internal complications, on the other hand, don't matter.
Should preferably exclude false positives completely. What I mean is: if you check for field foo_bar there is a small posibility that such field exists for a completely unrelated reason (and I think duck-typing is simply not for C++). A better way would be to check if type inherits marker class ProvidesExternalUseField from my library, as this can't be by accident.
EDIT
I know about Boost.Intrusive, but what I want is something different. If I go that way and create a hooks class with a single char field, it cannot be used to conserve memory in many cases. If inherited type has an int as first field, char field will be padded to 4 bytes. I.e. you'd often need intricate knowledge of type internals to be able to "squeeze" such extern-use field in, but inheritance doesn't really provide it:
struct hooks { mutable char dedicated_for_external_use; };
struct MyStuff : hooks
{
int foo;
char bar;
};
Here, size of MyStuff will be 12 bytes, not 8.
You can use partial template specialization for the case your data struct derives from the marker interface.
Let's say your marker interface class looks like this:
class ProvidesExternalUseField
{
public:
char GetExtraField () { return 0; }
void SetExtraField (char newVal) {}
};
It is not virtual for a purpose: we wouldn't want to add a vtable pointer to a data class just for this.
Now let's implement a simple container class:
template <class T>
class Container
{
public:
char GetExtraValue ()
{
return 0; // here we cannot know if T is derived from the marker
}
private:
T m_t;
};
And here is how we change it to distinguish between the 2 cases:
template <class T, bool DoesTProvideExternalUseField>
class ContainerImpl
{
public:
char GetExtraValue () { return 0; }
private:
T m_t;
};
template <class T>
class ContainerImpl<T, true>
{
public:
char GetExtraValue () { return m_t.GetExtraField(); }
private:
T m_t;
};
template <class T>
class Container: public ContainerImpl<T,
boost::is_base_of<ProvidesExternalUseField,T>::value>
{
};
Now you can define the structs like this:
struct A
{
int m_intVal;
};
struct B: public ProvidesExternalUseField
{
char GetExtraField () { return m_extraField; }
void SetExtraField (char newVal) { m_extraField = newVal; }
int m_intVal;
char m_charVal;
char m_extraField;
};
And use the container class in the exact same way:
Container<A> a;
Container<B> b;
You can also further automate (templatize) getters and setters in the marker interface by using a poiter-to-member as a template parameter.