template class with overridden operators - c++

I want to add a operator override to perform assignments/__set__s inline.
Template :-
class CBase {
public :
static void SetupVmeInterface(CVmeInterface *in);
protected :
static CVmeInterface *pVmeInterface;
};
template <class T> class TCVmeAccess : public CBase {
public:
TCVmeAccess(int address);
T get()
{
unsigned long temp = pVmeInterface->ReadAddress(Address);
T ret = *reinterpret_cast<T*>(&temp);
return ret;
};
T *operator->();
unsigned long asLong();
bool set(T data)
{
unsigned long write_data = *reinterpret_cast<unsigned long*>(&data);
return pVmeInterface->WriteAddress(Address, write_data);
};
// void operator->(T);
void operator=(T data)
{ set(data); }
private :
int Address;
};
A struct that will be used in the template :-
typedef struct
{
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
} _HVPSUControl;
Code body :-
TCVmeAccess<_HVPSUControl> HVPSUControl(constHVPSUControlBlock);
_HVPSUControl hvpsu = HVPSUControl.get(); // Yep, good, but not as nice as...
int a = HVPSUControl2.get().OperationalRequestPort; // yep, also good, but...
int b = HVPSUControl->a; // works, and is all go so far
HVPSUControl.set(hvpsu); // works, but need _HVPSUControl type
HVPSUControl = hvpsu; // also works, as operator = is used, but still need type
// this line does not work!
// as the = assignment is redirected into a copy of the struct, not the template
HVPSUControl->a = 1; // this line
So, is there a way to get this line above to work?
Edit:
As in, I want "this line" to perform as a "set" as does in the template class.
Edit:
1. Assign a value directly in-line to a member of the struct that the template is formed
of.
2. Cause that assignment to go though a template accessor.
So that I dont have to do this on assignments :-
// HVPSUControl is predefined and used many times.
_HVPSUControl hvpsu;
hvpsu.a = 1;
HVPSUControl.set(hvpsu);
I want to do
HVPSUControl.a = 1; // or
HVPSUControl->a = 1; // or ?
As gets work on line :
if (HVPSUControl->a)

Instead of overwriting the "->" and the "=" operator, you could derive from the template struct.
template <class T> class TCVmeAccess : public CBase, public T {
public:
TCVmeAccess(int address);
T get();
// T *operator->();
unsigned long asLong();
bool set(T);
// void operator->(T);
// void operator=(T);
private :
int Address;
};
HVPSUControl.a = 1; // and use this for setting a bitfield.
Edit: If you want to use an custom assignment operator, you should declare it in HVPSUControl, or a even a base class of it, if you have more of this control-like structures.
struct _HVPSUControl
{
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
void operator = (int x);
};
or
struct _HVPSUBase {
void operator = (int x);
}
struct _HVPSUControl: public _HVPSUBase
{
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
};

You can't get this line to work any other way. You call TCVmeAccess::operator-> which returns a _HVPSUControl* and then you access _HVPSUControl*::a.
Or do you want to assign integer 1 to the complete _HVPSUControl struct?
template <class T> class TCVmeAccess : public CBase {
public:
// ...
void operator=(T data) { set(data); }
void operator=(int n) { operator=(T(n)); }
// ...
};
typedef struct
{
_HVPSUControl(int n) {
*this = reinterpret_cast<_HVPSUControl>(n);
}
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
} _HVPSUControl;
and then do
HVPSUControl = 1;

Related

How to make an optional template parameter with a base class using CRTP?

How to make an optional template parameter with the base class using CRTP in the following code ?
template <unsigned int BYTES, OPTIONAL typename DerivedPrinter = MonoPrinter> //DerivedPrinter should be optional. If it is not specified then it should default to MonoPrinter.
class MonoPrinter
{
protected:
unsigned char CtrlCodes[BYTES] = { 0xFF }; //A code to initialize the printer
public:
MonoPrinter()
{
}
DerivedPrinter& print(const char* d)
{
for (int i=0; i<sizeof(CtrlCodes); i++)
SendCtrlCode(CtrlCodes[i]); //Initialize the printer and send additional control codes for color, font, etc...
printf("Print Me: %s\n", d); //This would actually send the string of chars to the printer (not to stdout) for printing
return static_cast<DerivedPrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
};
template <unsigned int BYTES>
class ColorPrinter : public MonoPrinter<BYTES, ColorPrinter>
{
public:
ColorPrinter() : MonoPrinter()
{
static_assert(sizeof(CtrlCodes) >= 4);
CtrlCodes[1] = 0xAA;
CtrlCodes[2] = 0xBB;
CtrlCodes[3] = 0xC0;
}
ColorPrinter& SetColor(unsigned char c)
{
CtrlCodes[3] = c;
return *this;
}
};
void main(void)
{
MonoPrinter<1> iMonoPrinter;
ColorPrinter<4> iColorPrinter;
iMonoPrinter.print("Hello World").print(" we have no color");
iColorPrinter.print("Hello World").SetColor(BLUE).print(" in Living Color");
}
P.S.
The above code is a contrived and abridged for simplicity. The "BYTES" template parameter is not optional and it always must be specified.
I have other problems with this code, but the main one is how to make the "DerivedPrinter" template parameter optional, so it does not always have to be specified ...and when it is not - it should default to the base class itself.
I guess you can (see code below), but I think it's not necessary in this case (see second example).
First example, with the optional template parameter (note that here the PrinterTpl template inherits directly from the concrete BasePrinter, so all derived classes, MonoPrinter and ColorPrinter here, are inheriting from BasePrinter):
template <unsigned int BYTES>
class BasePrinter
{
protected:
unsigned char CtrlCodes[BYTES] = { 0xFF };
public:
BasePrinter()
{
SendCtrlCode(CtrlCodes[0]); //Initialize the printer
}
};
template <unsigned int BYTES, typename DerivedPrinter = BasePrinter<BYTES>> //DerivedPrinter should be optional. If it is not specified then it should default to PrinterTpl.
class PrinterTpl : public BasePrinter<BYTES>
{
public:
PrinterTpl() : BasePrinter<BYTES>()
{
}
DerivedPrinter& print(const char* d)
{
printf("Data: %s\n", d);
return static_cast<DerivedPrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
};
template <unsigned int BYTES>
class MonoPrinter : public PrinterTpl<BYTES, MonoPrinter<BYTES>>
{
public:
MonoPrinter() : PrinterTpl<BYTES, MonoPrinter<BYTES>>()
{
}
};
template <unsigned int BYTES>
class ColorPrinter : public PrinterTpl<BYTES, ColorPrinter<BYTES>>
{
public:
ColorPrinter() : PrinterTpl<BYTES, ColorPrinter<BYTES>>()
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
this->CtrlCodes[1] = 0xC1;
this->CtrlCodes[2] = 0xC2;
this->CtrlCodes[3] = 0xC3;
}
ColorPrinter& SetColor(int c)
{
assert(c < sizeof(this->CtrlCodes));
SendCtrlCode(this->CtrlCodes[c+1]);
return *this;
}
};
Second example, no template optional parameter (here the template PrinterTpl doesn't need to inherit from a base):
template <unsigned int BYTES, typename ConcretePrinter>
class PrinterTpl
{
protected:
unsigned char CtrlCodes[BYTES] = { 0xFF };
public:
PrinterTpl()
{
SendCtrlCode(this->CtrlCodes[0]); //Initialize the printer
}
ConcretePrinter& print(const char* d)
{
printf("Data: %s\n", d);
return static_cast<ConcretePrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
};
template <unsigned int BYTES>
class MonoPrinter : public PrinterTpl<BYTES, MonoPrinter<BYTES>>
{
public:
MonoPrinter() : PrinterTpl<BYTES, MonoPrinter<BYTES>>()
{
}
};
template <unsigned int BYTES>
class ColorPrinter : public PrinterTpl<BYTES, ColorPrinter<BYTES>>
{
public:
ColorPrinter() : PrinterTpl<BYTES, ColorPrinter<BYTES>>()
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
this->CtrlCodes[1] = 0xC1;
this->CtrlCodes[2] = 0xC2;
this->CtrlCodes[3] = 0xC3;
}
ColorPrinter& SetColor(int c)
{
assert(c < sizeof(this->CtrlCodes));
SendCtrlCode(this->CtrlCodes[c+1]);
return *this;
}
};
If I am not mistaken, this should achieve your goal and it's cleaner in my opinion.
The key to being able to write MonoPrinter<1> instead of MonoPrinter<1,dummy> and making the 2nd template parameter optional was the following conditional typedef typenameinside the base class template:
typedef typename std::conditional< std::is_same<Derived, void >::value, MonoPrinter, Derived >::type DerivedPrinter; //Default to the MonoPrinter class if Derived == void
The code below now compiles without errors and does not require the creation of a 3rd class template. See: https://godbolt.org/g/awuck7
#include <type_traits>
#include <stdio.h>
#define BLUE 3
template <unsigned int BYTES, typename Derived = void>
class MonoPrinter
{
typedef typename std::conditional< std::is_same<Derived, void >::value, MonoPrinter, Derived >::type DerivedPrinter; //Default to the MonoPrinter class if Derived == void
protected:
unsigned char CtrlCodes[BYTES];
const unsigned char FinCode = 0xFF;
public:
void SendCtrlCode(unsigned char c)
{
printf("<%02X>", c); //This would actually send the string of control chars to the printer (not to stdout)
}
void InitializePrinter(void)
{
printf("\n");
SendCtrlCode(CtrlCodes[0]);
SendCtrlCode(0x00);
SendCtrlCode(FinCode);
}
MonoPrinter()
{
CtrlCodes[0] = 0xEE; //Set the default printer escape code
InitializePrinter();
}
MonoPrinter(unsigned char c)
{
CtrlCodes[0] = c; //A custom printer escape code
InitializePrinter();
}
DerivedPrinter& print(const char* d)
{
for (int i = 0; i < sizeof(CtrlCodes); i++)
SendCtrlCode(CtrlCodes[i]); //Initialize the printer and send additional control codes for color, font, etc...
SendCtrlCode(FinCode);
printf("%s", d); //This would actually send the string of chars to the printer (not to stdout) for printing
return static_cast<DerivedPrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
int FooFn()
{
return 333;
}
};
template <unsigned int BYTES>
class ColorPrinter : public MonoPrinter<BYTES, ColorPrinter<BYTES>>
{
protected:
using MonoPrinter<BYTES, ColorPrinter<BYTES>>::CtrlCodes;
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::FinCode;
public:
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::MonoPrinter;
using MonoPrinter<BYTES, ColorPrinter<BYTES>>::FooFn;
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::InitializePrinter;
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::SendCtrlCode;
ColorPrinter()
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
CtrlCodes[1] = 0xDD;
CtrlCodes[2] = 0xEE;
CtrlCodes[3] = 0xC0; //Default Color value
}
ColorPrinter(unsigned char c) : MonoPrinter<BYTES, ColorPrinter<BYTES>>::MonoPrinter(c)
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
CtrlCodes[1] = 0xDD;
CtrlCodes[2] = 0xEE;
CtrlCodes[3] = 0xC0; //Default Color value
}
ColorPrinter& SetColor(unsigned char c)
{
CtrlCodes[3] = c;
return *this;
}
int BooFn()
{
return FooFn() + 1;
}
};
int main(void)
{
MonoPrinter<1> iMonoPrinter;
ColorPrinter<4> iColorPrinter(0xCC);
iMonoPrinter.print("Hello World").print(" we have no color \n");
iColorPrinter.print("Hello World").SetColor(BLUE).print(" in Living Color \n");
printf(" %d\n", iColorPrinter.FooFn());
printf(" %d\n", iColorPrinter.BooFn());
return 0;
}

How to use an integer id to identify a class in a class hierarchy automatically?

For example, I have a base class A and its sub-classes B, C and so on. B and C can also has its sub-classes. The structure is a tree with root A. And each class in the tree is assigned a different integer to identify itself. There is no restriction on the integer id's values and orders. Just make sure they are different for different classes.
My question is how to do it smartly (or automatically) by using like template techniques since manual assignment is error-prone. Any way to get the id is fine, like
class A
{
public:
static const id = ...;
};
or
template<class A>
struct Id
{
enum { value = ... };
};
Easiest way is just a function
int nextId() {
static int rval = 1;
return rval++;
}
class A { public: static const id = nextId(); };
class B { public: static const id = nextId(); };
class C { public: static const id = nextId(); };
That will work so long as you do not need to use the IDs in dynamic initialization at the start of the program.
Edit: if that is not sufficient, the next step up is to do the same thing with static variables in a template. This works across compilation units, but is still dynamic initialization time.
template <typename DummyT = void>
struct CommonCounter
{
public:
static int nextId() {
static int rval = 1;
return rval ++;
}
};
template <typename T>
struct IdFor
{
static int value()
{
static int rval = CommonCounter<>::nextId();
return rval;
}
};
class A { public: static const id = IdFor<A>::get(); };
You could do something like this. This should give the same order on the same compiler. You could also modify how you key things to get a known order and detect problems at initialisation time. Simple implementation, not tested.
#include <typeinfo>
class A {
public:
virtual ~A();
static void register_type(std::type_info const& t);
int id() const;
};
template<class T>
struct DoInitA
{
DoInitA() { A::register_type(typeid(T)); }
};
class B : public A
{
static DoInitA<B> s_a_init;
public:
~B() { }
};
//
// Implementation file.
//
#include <vector>
#include <functional>
namespace {
struct TypeinfoLess {
typedef std::reference_wrapper<const std::type_info> value_type;
bool operator()(value_type const& lhs, value_type const& rhs) const {
return lhs.get().before(rhs.get());
}
};
}
typedef std::vector<std::reference_wrapper<const std::type_info>> TypeVector;
static TypeVector s_types;
static bool s_init_complete = false;
A::~A() { }
void A::register_type(std::type_info const& t)
{
static int s_counter = 0;
if (s_init_complete)
throw std::runtime_error("Late initialisation");
s_types.push_back(std::reference_wrapper<const std::type_info>(t));
}
int A::id() const
{
if (!s_init_complete) {
sort(s_types.begin(), s_types.end(), TypeinfoLess());
s_init_complete = true;
}
for (size_t i = 0; i < s_types.size(); ++i)
if (s_types[i].get() == typeid(*this)) return i;
throw std::runtime_error("Uninitialised type");
}

member variable and constructor dependent on template parameter

In C++11, I'd like to have a member variable in a class and a constructor for its initialization only if its default template value was chosen (only for supported types like int, of course).
What are recommended ways to achieve this (boost allowed)?
Something like:
template< int _x = -1 > struct C {
C() {} // only available if _x != -1
C( int x ) : x( x ) {} // only available if _x == -1
// more methods that are common for all _x and refer to _x / x
private:
int x; // only available if _x == -1
// more members that are common for all _x
};
Or, put in another way: For size and speed optimization, I would like to use a compile time constant instead of a value stored in a member variable if another value than the template default was chosen.
--
Here is an example to make everything clearer:
template< int _size = -1 > struct Block {
Block() { buf = mmap( _size, ... ); } // exists only when size!=-1
Block( int s ) { buf = mmap( size = s, ... ); } // exists only when size==-1
~Block() { munmap( buf, getSize() ); } // should use the correct size
int getSize() const { return ???; } // gets _size if !=-1, size otherwise
// other methods that use buf and getSize()
private:
void *buf;
const int size; // only exists for size == -1!
};
This solves it partially:
template< int _x > struct X {
int getX() const { return _x; }
};
template<> struct X< -1 > {
X( x ) : x( x ) {}
int getX() const { return _x; }
private:
int x;
};
template< int _x = -1 > struct C : X< _x > {
C() {} // only available if _x != -1
C( int x ) : X< _x >( x ) {} // only available if _x == -1
// more methods that are common for all _x and use this->getX()
};
But what about the constructors of C, and are other / nicer solutions available?
Just an idea, but maybe it helps: You could try to use a base class only for the minimal differences and "fake" the member variable for when it's not there to allow the rest to compile:
template< int _x > class B
{
public:
B() {}
protected:
static const int x = _x;
};
template<> class B< -1 >
{
public:
B( int i ) : x( i ) {}
protected:
int x;
};
template< int _x = -1 >
class C : public B<_x>
{
public:
using B<_x>::B; // inherit B's ctors
void f()
{
if ( x == ... ) // uses either the member variable x or the static const int x!
}
};
but as I said, it's just an idea...
Specialization is the way to go:
template <int N> struct C
{
C(int n) : n_(n) { }
int n;
};
template <> struct C<-1>
{
C() { }
C(int n) : n_(n) { }
int n;
};
I'm with Kerrek SB on this one. Put your common code, namely the runtime buffer handling in a common base class an create two derived classes, one for your statically sized buffer class and one for your dynamic buffer class. Or better yet, according to common coding guidelines, use composition.
class buffer_impl {
public:
buffer_impl(int size) : data_ {mmap( size, ... )}, size_ {size} {}
~buffer_impl() { munmap( data_, getSize() ); }
int getSize() const noexcept { return size_; }
// other buffer routines
// ...
private:
void* data_;
int size_;
};
template <int _size = -1 >
class buffer { // static size
public:
buffer() : impl_ {_size} {}
static constexpr int getSize() noexcept { return _size; }
private:
buffer_impl impl_;
};
template <>
class buffer<-1> { // dynamic size
public:
buffer(int size) : impl_ {size} {}
int getSize() const noexcept { return impl_.getSize(); }
private:
buffer_impl impl_;
};

Polymorphic static const member variables in an ABC?

I have a rather strange situation where I would like to be able to define certain constants that a subclass of an ABC can override.
struct A {
static const int a = 20;
virtual int func() = 0;
};
struct B : public A {
static const int a = 3;
int func() { return 5; }
};
struct C : public A {
static const int a = 4;
int func() { return 3; }
};
Unfortunately, if I use A *aPtr = new B, aPtr->a will return 20, instead of 3.
One workaround I see is one-liner functions (along the lines of func in the above example), but the syntax of constants is quite a bit more appropriate for this particularly situation conceptually. Is there a syntactically reasonable way of resolving which constants to use at runtime, where the calling code doesn't need to know anything after initial object creation?
Constants, especially static constants, cannot be overriden like you are asking for. You would have to use a virtual function instead:
struct A {
virtual int get_a() { return 20; }
int func() = 0;
};
struct B : public A {
virtual int get_a() { return 3; }
int func() { return 5; }
};
struct C : public A {
virtual int get_a() { return 4; }
int func() { return 3; }
};
Another option would be to use a template for the constant instead:
template< const int a_value = 20 >
struct A {
static const int a = a_value;
int func() = 0;
};
struct B : public A<3> {
int func() { return 5; }
};
struct C : public A<4> {
int func() { return 3; }
};
You can get answer from the example itself ! :) Just declare a method like get_a() which is virtual and override the same.
struct A {
static const int a = 20;
virtual int get_a() const { return a; } // <--- for A
};
struct B : public A {
static const int a = 3;
virtual int get_a() const { return a; } // <--- for B
};
struct C : public A {
static const int a = 4;
virtual int get_a() const { return a; } // <--- for C
};
Also note that, only method can be overridden in C++ and not the variables.

C++ : Initializing base class constant static variable with different value in derived class?

I have a base class A with a constant static variable a. I need that instances of class B have a different value for the static variable a. How could this be achieved, preferably with static initialization ?
class A {
public:
static const int a;
};
const int A::a = 1;
class B : public A {
// ???
// How to set *a* to a value specific to instances of class B ?
};
You can't. There is one instance of the static variable that is shared by all derived classes.
Static members are unique in the application. There is a single A::a constant in your system. What you can do is create a B::a static constant in B that will hide the A::a static (if you don't use the fully qualified name:
class A {
public:
static const int a = 10;
};
static const int A::a;
class B : public A {
public:
static const int a = 20;
static void test();
};
static const int B::a;
void B::test() {
std::cout << a << std::endl; // 20: B::a hides A::a
std::cout << A::a << std::endl; // 10: fully qualified
}
You can do this with Curiously recurring template pattern (you'll have to lose the const though).
template <typename T>
class A {
public:
static int a;
};
template <typename T>
int A<T>::a = 0;
class B : public A<B> {
struct helper { // change the value for A<B>::a
helper() { A<B>::a = 42; }
};
static helper h;
};
B::helper B::h;
May be we can try this way as below ::
The benefit of the below is that you don't have to write the code multiple times, but the actual generated code might be big.
#include <iostream>
using namespace std;
template <int t>
class Fighters {
protected :
static const double Fattack;
double Fhealth;
static const double Fdamage;
static int count;
public :
Fighters(double Fh) : Fhealth(Fh) { }
void FighterAttacked(double damage) {
Fhealth -= damage;
}
double getHealth()
{
return Fhealth;
}
static int getCount()
{
//cout << count << endl;
return count;
}
};
const double Fighters<1>::Fdamage = 200.0f;
const double Fighters<1>::Fattack = 0.6f;
int Fighters<1>::count = 0;
class Humans : public Fighters<1> {
public :
Humans(double Fh = 250) : Fighters<1>(Fh) { count++; }
};
const double Fighters<2>::Fdamage = 40.0f;
const double Fighters<2>::Fattack = 0.4f;
int Fighters<2>::count = 0;
class Skeletons : public Fighters<2> {
public :
Skeletons(double Fh = 50) : Fighters<2>(Fh) { count++; }
};
int main()
{
Humans h[100];
Skeletons s[300];
cout << Humans::getCount() << endl;
cout << Skeletons::getCount() << endl;
return 0;
}
This is part of my other code example .. don't mind many other data but concept can be seen.