I would like to be able to provide to the base class MCFormater a formatting method that would work for different types (uint32, uint8...)
class MCFormater {
public:
MCFormater() {}
virtual ~MCFormater() {}
virtual mcc_t Gen();
protected:
template<typename K> //here is the problem
virtual void Format(K& a, const K& b) = 0;
//...
uint32_t a;
uint8_t b;
void Foo();
};
void MCFormater::Foo() {
Format<uint32_t>(a, 3); //I want to be able to call for Format
Format<uint8_t>(b, 3); //with uint32_t, and uint8_t, and more
}
class GFormater : public MCFormater {
GFormater() {}
template<typename K>
virtual void Format(K& a, const K& b) {
a = b;
}
};
class EFormater : public MCFormater {
EFormater() {}
template<typename K>
virtual void Format(K& a, const K& b) {
a |= b;
}
};
but I get the error: templates may not be 'virtual'.
what is the right way to do it? (is there one?)
Modify...
class MCFormater {
public:
MCFormater() {}
virtual ~MCFormater() {}
virtual mcc_t Gen();
protected:
template<typename K> //here is the problem
virtual void Format(K& a, const K& b) = 0;
//...
uint32_t a;
uint8_t b;
void Foo();
};
void MCFormater::Foo() {
Format<uint32_t>(a, 3);
Format<uint8_t>(b, 3);
}
class GFormater : public MCFormater {
GFormater() {}
template<typename K>
virtual void Format(K& a, const K& b) {
a = b;
}
};
class EFormater : public MCFormater {
EFormater(FTEKeeps* keeps) : MCFormater(keeps) {}
template<typename K>
virtual void Format(K& a, const K& b) {
a |= b;
}
};
To...
#include<iostream>
using namespace std;
template<typename K>
class MCFormater {
public:
MCFormater() {}
virtual ~MCFormater() {}
virtual mcc_t Gen();
protected:
virtual void Format(K& a, const K& b) = 0;
//...
uint32_t a;
uint8_t b;
void Foo();
};
template<typename K>
void MCFormater<K>::Foo() {
Format<uint32_t>(a, 3);
Format<uint8_t>(b, 3);
}
template<typename K>
class GFormater : public MCFormater<K> {
GFormater() {}
virtual void Format(K& a, const K& b) {
a = b;
}
};
template<typename K>
class EFormater : public MCFormater<K> {
EFormater(FTEKeeps* keeps) : MCFormater<K>(keeps) {}
virtual void Format(K& a, const K& b) {
a |= b;
}
};
Explanation: Member function templates cannot be virtual. If this was allowed then the linker would have to add a new entry to the virtual table every time the Format function was called with a different type. Dynamic linking would be unacceptably complicated.
Related
Consider the following classes,
template <class L>
class A {
public:
A(L l) : _l(l) {}
private:
L _l;
};
class B {
public:
B(int x) : _x(x), _a([this]() { return _x; }) {}
private:
int _x;
A<???> _a;
};
I am not sure how to specify the type at ???. std:: function<int()> works, but to my knowledge, this implies virtual function calls (of course, this does not have to be bad, but it would be interesting how to do this properly).
Rather than a lambda, you can use a function object that's roughly equivalent.
template <class L>
class A {
public:
A(L l) : _l(l) {}
private:
L _l;
};
class B {
struct GetX
{
int operator()() const { return _b->_x; }
B * _b;
};
public:
B(int x) : _x(x), _a(GetX{ this }) {}
private:
int _x;
A<GetX> _a;
};
I have the following code:
class A
{
public:
virtual void f(int a) = 0;
virtual void f(int a, int b) = 0;
};
class B : public A
{
public:
// do not want f(int a,int b) accessible
void f(int a);
};
class C : public A
{
public:
// do not want f(int a) accessible
void f(int a, int b);
};
I am aware that purely virtual functions cannot be deleted. Is there any way to disable these functions such that a compile time error occurs if an instance of B tries to call f(int,int) or when an instance of C tries to call f(int)
There's no way to do that. You'd need a more complex class hierarchy. Something like this:
class A
{
public:
virtual ~A() {}
};
class BaseForB : public A
{
public:
virtual void f(int a) = 0;
};
class BaseForC : public A
{
public:
virtual void f(int a, int b) = 0;
};
class B : public BaseForB
{
public:
void f(int a) override
{
// details...
}
};
class C : public BaseForC
{
public:
void f(int a, int b) override
{
// details...
}
};
One option is to put a class between A B and A which implements a private version of the function that is final and not callable by instances of B like this:
class A
{
public:
virtual void f(int a) = 0;
virtual void f(int a, int b) = 0;
};
class A_B : public A {
using A::f;
private:
void f(int a, int b) final override {}
};
class B : public A_B
{
public:
// do not want f(int a,int b) accessible
void f(int a);
};
I have an interface and a class implementing it:
class InterfaceA
{
public:
enum Enum { X, Y, Z };
virtual void foo(Enum &) = 0;
virtual void bar() = 0;
};
class ClassA : public InterfaceA
{
public:
virtual void foo(Enum & a) {
a = X;
}
virtual void bar();
};
I need to extend the functionality of an InterfaceA implementing class in one aspect. In my understanding this is what mixins are for.
E.g. foo() should change its parameter value on some condition. Here is how I do it:
template <typename T>
class Mixin : public T
{
public:
virtual void foo(Enum & a) {
T::foo(a);
if (a == X){
a = Y;
}
}
};
The problem is, it won't compile unless I either write scope prefixes to identifiers defined in the interface class or typedef them like this:
template <typename T>
class Mixin : public T
{
public:
typedef InterfaceA::Enum Enum;
virtual void foo(Enum & a) {
T::foo(a);
if (a == InterfaceA::X){
a = InterfaceA::Y;
}
}
};
It's not a big deal if there are few such types coming from the interface definition. But if there are many, it can become ugly. I would like the code to reflect the fact that a Mixin manipulates an InterfaceA object by design. Unfortunately inheriting Mixin from InterfaceA introduces a 'dreaded diamond' which I'd better avoid. Is that possible?
Enum, X and Y should be dependent typename.
And you may use static_assert to force inheritance.
template <typename T>
class Mixin : public T
{
public:
static_assert(std::is_base_of<InterfaceA, T>::value,
"T should inherit from InterfaceA");
virtual void foo(typename T::Enum & a) {
T::foo(a);
if (a == T::X){
a = T::Y;
}
}
};
I suppose you should use virtual inheritance; this should avoid "dreaded diamond" problem.
Something like
class InterfaceA
{
public:
enum Enum { X, Y, Z };
virtual void foo(Enum &) = 0;
virtual void bar() = 0;
};
class ClassA : public virtual InterfaceA
{
public:
virtual void foo(Enum & a) {
a = X;
}
virtual void bar() {
}
};
template <typename T>
class Mixin : public T, public virtual InterfaceA
{
public:
virtual void foo(Enum & a) {
T::foo(a);
if (a == X){
a = Y;
}
}
};
int main ()
{
Mixin<ClassA> m;
return 0;
}
What I mean is modifying the following code, X declaration to be exact, so that I can use an object B of any kind, B<int>, B<real> ... Sadly, it's important I have an Obj<T> *pobj in B.
template <typename T>
class Obj
{
public:
T a;
public:
Obj(T a_) : a(a_) {}
void print() const
{ std::cout << "a : " << a << std::endl; }
};
template <typename T>
class A
{
public:
Obj<T> *pObj;
public:
A(Obj<T>* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<double> X;
};
Obj<double> X = Obj<double>(1.0);
template <typename T>
class B : public A<T>
{
public:
B() : A<T>( &X ) {}
void doSmthg()
{ X.print(); }
};
// in main
B<int> b;
b.doSmthg();
That code will return no known conversion for argument 1 from ‘Obj<double>*’ to ‘Obj<int>*’
You might approach it like this:
struct ObjBase
{
virtual void print() const = 0;
};
template <typename T>
class Obj : public ObjBase
{
public:
T a;
public:
Obj(T a_) : a(a_) {}
virtual void print() const
{ std::cout << "a : " << a << std::endl; }
};
template <typename T>
class A
{
public:
ObjBase *pObj;
public:
A(ObjBase* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<double> X;
};
That is, have a base class that provides an interface for the things that you want to do that are not dependent on the particular type.
Answering myself.
It is ... I forgot the qualification in my tests..
template <typename T>
class A
{
public:
Obj<T> *pObj;
public:
A(Obj<T>* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<T> X;
};
template<typename T>
Obj<T> Obj<T>::X(1.0);
I have the following class:
class ValueSetter: public IValueSetter
{
public:
explicit ValueSetter(CContainer* container)
: _container(container)
{
}
virtual void operator()(const int value, const int index) const
{
_container->values[index].value.i = value;
}
virtual void operator()(const double value, const int index) const
{
_container->values[index].value.d = value;
}
virtual void operator()(const std::string& value, const int index) const
{
...
_container->values[index].value.s = _strdup(value.c_str());
}
private:
CContainer* _container;
};
This class operates on CContainer which stores its data in a buffer of unions. I pass ValueSetter to a Container class which has no knowledge of CContainer. Indeed, in the future I'm hoping that CContainer (which I received via a C API) will disappear and that the values are instead organised in a std::vector or std::list. My Container's interface shouldn't need to change because of this and shouldn't care about how the data is stored in memory.
With this in mind, I'd prefer instead something roughly along these lines:
class IntValueSetter: public IIntValueSetter
{
public:
explicit IntValueSetter(Container* container)
: _container(container)
{
}
virtual void operator()(const int value, const int index) const
{
_container->values[index].value.i = value;
}
private:
CContainer_3* _container;
}
or:
class IntValueSetter: public IIntValueSetter
{
public:
explicit IntValueSetter(std::vector<int> values)
: _values(values)
{
}
...
}
but I'd need to be able to use them as follows:
ValueSetter<int> valueSetter;
instead of
IntValueSetter valueSetter;
How can I do this?
Just do the obvious. There's no requirement that a template specialization have anything in common with another specialization or with the original template. So:
class IIntValueSetter {
};
template <class Ty> class ValueSetter; // declared but not defined
template <>
class ValueSetter<int> : public IIntValueSetter {
// whatever
};
ValueSetter<int> vsi;
If I get you right, you just need to write a class template:
template <typename T>
class ValueSetter
{
public:
explicit ValueSetter(std::vector<T> values): _values(values)
{
}
virtual void operator()(const T value, const int index) const
{
_container->values[index].value.i = value;
}
// etc.
};
I guess I'm looking for something like this. I've only implemented for int below, but each type would get its own interface class and implementation class. I'd love to hear your comments on this approach!
template<typename V>
class IValueSetter
{
public:
};
template<>
class IValueSetter<std::string>
{
public:
virtual void operator()(const std::string& value, int index) const = 0;
};
template<typename V>
class ValueSetter
{
};
template<>
class ValueSetter<std::string>: public IValueSetter<std::string>
{
public:
explicit ValueSetter2(CContainer* container)
: _container(container)
{
}
void operator()(const std::string& value, int index) const
{
_container->values[index].value.s = _strdup(value.c_str());
}
private:
CContainer* _container;
};
template<>
class NewValueSetter<std::string>: public IValueSetter<std::string>
{
public:
explicit NewValueSetter(std::shared_ptr<std::list<std::string>> values)
: _values(values)
{
}
void operator()(const std::string& value, int index) const
{
(*values)[index] = value;
}
private:
std::shared_ptr<std::list<std::string>> _values;
};