Template class on a abstract class - c++

So I have a class template Foo:
template <typename T>
class Foo
{
public:
Foo();
~Foo();
//...
};
I have two derived classes from the Foo class:
class FooDerived1 : public Foo<int>
{
public:
FooDerived1 ();
~FooDerived1 ();
};
class FooDerived2 : public Foo<double>
{
public:
FooDerived2 ();
~FooDerived2 ();
};
But now I saw that the class template was being used on a abstract class IBar like this:
class Foo;
class IBar
{
public:
virtual void placeFoo(Foo& foo) = 0; //error
virtual void removeFoo(Foo& foo) = 0;
};
I know I cannot use templates classes in abstract virtual classes.
But..in a case like this, what should I do?
I really need the IBar abstract class like this...
Forget the usage of template classes?

Option 1: Make IBar itself a template class.
template <class T>
class Foo;
template <class T>
class IBar
{
public:
virtual void placeFoo(Foo<T>& foo) = 0;
virtual void removeFoo(Foo<T>& foo) = 0;
};
Option 2: Make all Foo<T> derive from a common, non-generic FooBase.
class FooBase
{
// ...
};
template <typename T>
class Foo : public FooBase
{
public:
Foo();
~Foo();
//...
};
// ...
class FooBase;
class IBar
{
public:
virtual void placeFoo(FooBase& foo) = 0;
virtual void removeFoo(FooBase& foo) = 0;
};
The viability of both solutions depends on how much you actually depend on the T type. But that's what you should expect when you mix virtual functions with templates. With option 1, you do not have a common interface type anymore; with option 2, FooBase cannot provide any member function with a T-dependent argument.
By the way, don't forget about virtual destructors in your real code.

If you need common behaviour, create base class for all instances of Foo<>:
class FooBase
{
//common interface and data
};
template <class T>
class Foo : public FooBase
{
};
And then:
class FooBase;
class IBar
{
public:
virtual void placeFoo(FooBase& foo) = 0; //ok
virtual void removeFoo(FooBase& foo) = 0;
};
The thing is, that you try to mix templates (compile time) and dynamic polymorphism (runtime), which can be problematic (is it what you meant by "I know I cannot use templates classes in abstract virtual classes"?).
Why not stick to using templates?
class IBar
{
public:
template <class T>
void placeFoo(Foo<T>& foo);
template <class T>
void removeFoo(Foo<T>& foo);
};
or:
template <class T>
class IBar
{
public:
void placeFoo(Foo<T>& foo);
void removeFoo(Foo<T>& foo);
};

Related

C++ Polymorphic template class, instantiation of template type object

I have the following situation, where I want to instantiate an object of a template type.
I want the instantiation of the template type object to depend on the "instantiator" class.
template <class T>
class Base
{
public:
Base(){}
void do_something()
{
T obj = this->Test();
// do something with object
}
virtual T Test()
{
return T(5);
}
};
template <class T>
class Derived : public Base<T>
{
public:
Derived() : Base<T>() {}
virtual T Test()
{
return T(5, 6);
}
};
class Test1
{
public:
Test1(int x){}
};
class Test2 : public Test1
{
public:
Test2(int x, int y) : Test1(x) {}
};
Later in my code I want to work with Base or Derived objects.
They perform operations on a template type object (obj) in function do_something().
I want to let the instantiation of obj depend on the implementation
of the Test() function.
Base should only work with objects of type Test1 or derived classes of Test1 that have the same constructor.
Derived should only work on objects that have the same constructor as Test2.
Base<Test1>(); // works
Base<Test2>(); // doesn't work, but should not work by my design and throw a compile error
Derived<Test1>(); // same
Derived<Test2>(); // should work, but doesn't,
// since Base::Test() still exists, but cannot be compiled due to wrong constructor of T
Is there a way to implement the described behavior?
Or is there a design change I can make?
You might change Base to be correct for any T:
template <class T>
class Base
{
public:
Base(){}
void do_something()
{
T obj = this->Test();
// do something with object
}
virtual T Test()
{
if constexpr (std::is_constructible_v<T, int>) {
return T(5);
}
throw std::runtime_error("should not be called");
}
};
but
Base<Test2>(); would compile but throw at runtime.
Seems better to split and have two derived:
template <class T>
class Base
{
public:
Base() = default;
virtual ~Base() = default;
void do_something()
{
T obj = this->Test();
// do something with object
}
virtual T Test() = 0;
};
template <class T>
class Derived : public Base<T>
{
public:
Derived() : Base<T>() {}
T Test() override { return T(4); }
};
template <class T>
class Derived2 : public Base<T>
{
public:
Derived() : Base<T>() {}
T Test() override { return T(5, 6); }
};

Mocking classes with template methods

Is there any pattern for testing classes that use classes containing template methods in public api? I know that in dynamic polymorphism mocking interface is the solution like this:
struct Interface {
virtual void foo() = 0;
virtual ~Interface() = default;
};
class TestedClass {
public:
TestedClass(Interface& i) {}
// ... rest of the class
};
struct IMock : public Interface {
void foo() override {}
};
void test() {
IMock bar;
TestedClass baz(bar);
}
But what can I do with something like below? Is there an idiomatic way to test this?
struct Interface {
template<class T>
void foo() {
// do stuff depending on type
}
};
class TestedClass {
public:
TestedClass(Interface& i) {}
// ... rest of the class
// uses Interface foo with multiple types
};
To allow mocking, in that case, you need
template <typename InterfaceT> class TestedClass;
so you can now have TestedClass<Interface> (for production) and TestedClass<MockInterface> (for testing).
struct Interface {
template<class T>
void foo() {
// do stuff depending on type
}
};
template <typename InterfaceT>
class TestedClass {
public:
TestedClass(InterfaceT& i) {}
// ... rest of the class
// uses Interface foo with multiple types
};
struct MockInterface {
template<class T>
void foo() {
// do mock-stuff depending on type
}
};
void test() {
MockInterface bar;
TestedClass baz(bar); // Or pre CTAD of C++17: TestedClass<MockInterface> baz(bar);
}

Templated class unknown type over multiple layers

I've got following class Foo and FooBase:
class FooBase
{
public:
virtual void A() = 0;
};
template <class T>
class Foo : public FooBase
{
public:
virtual void A() {}
private:
T mT;
};
FooBase is here to have a instance without needing to know the type, so I can do s.th. like this:
FooBase *foo = new Foo<int>();
Pretty standard. Now the issue: I want to bring the same thing to the next level.
So I've got the class:
template <class T>
class Bar : public Foo<T>
{
public:
virtual void B() {}
};
And can of course use:
Bar<int> *bar = new Bar<int>();
Except I don't know the type of the template class.
So initial idea was to do the following:
class BarBase : public FooBase
{
public:
virtual void B() {}
};
template <class T>
class Bar : public BarBase, Foo<T>
{
};
So I can do the following:
BarBase *bar = new Bar<int>();
For obvious reasons this doesn't work - the question is now: How to get s.th. like this to work?
You can solve this issue with virtual inheritance. This feature assures that there is only one instance of your virtually-inherited base class when you instantiate a subclass. For your example, this would look like:
class FooBase
{
public:
virtual void A() = 0;
};
template <class T>
class Foo : public virtual FooBase
// ^^
{
public:
virtual void A() {}
private:
T mT;
};
class BarBase : public virtual FooBase
// ^^
{
public:
virtual void B() {}
};
template <class T>
class Bar : public BarBase, Foo<T>
{
};
Now you can happily create instances like you wanted:
BarBase *bar = new Bar<int>();

C++ how to implement conditional inheritance with the following example

What I want to doe is a simple conditional inheritance in the Foo class
so depending on how it's instanciated (see usage)
class BaseType
{
protected:
m_valueX;
public: BaseType(int param = 0):m_valueX(param){}
~ BaseType(){}
}
...
class Type1 : public BaseType
{
public: Type1():BaseType(1){}
~Type1(){}
}
...
class Type2 : public BaseType
{
public: Type2(): BaseType(2){}
~Type1(){}
}
...
template<typename Base>
class Foo: public Base
{
public:
Foo(){}
~Foo();
void dothis();
}
...........
in cpp file
template<typname Base>
Foo<Base>::Foo():Base()
{
}
Foo::~Foo(){}
void Foo::dothis(){}
usage:
Foo* fooptr1 = new Foo<Type1>();<== error use of class template requires template argument list
Foo* fooptr2 = new Foo<Type2>();>();<== error use of class template requires template argument list
Thank you!
Foo is a template, not a class. The common class type for all Foo<T> is Base, so you can say:
Base * p1 = new Foo<Type1>;
Base * p2 = new Foo<Type2>;

Accessing protected member of template parameter

I have a template class for which I need to access a protected member function of the template parameter, like this:
class Foo
{
protected:
void foo() {}
};
template<typename T>
class Bar
{
public:
static void bar(T& self){self.foo();}
};
...
Foo f;
Bar<Foo>::bar(f);
My problem is getting access to the protected method. I tried putting a friend class T into Bar, but that doesn't seem to be allowed in c++ (edit: and wouldn't solve my problem anyways, so it seemd). I tried letting Bar inherit from T (template<typename T> class Bar: public T (could have used private inheritance, but the public interface of Bar is not terribly important, since the class itself is internal only)), but that didn't allow for access of foo() either. So how do I get access to the foo() method?
Edit:
Foo should not need to know Bar<Foo>, since there are quite a lot Bar classes. I can however make other changes to Foo (without changing the public interface of course).
OK, this is a "rot in hell" hack. You can abuse the fact that you can form pointers-to-members pointing to protected base members from a derived class.
class Foo
{
protected:
void foo() {}
};
// Helper template to bypass protected access control
// for a member function called foo, taking no parameters
// and returning void.
template<typename T>
struct Unprotect : public T
{
typedef void (T::*FooPtr)();
static FooPtr GetFooPtr()
{
return &Unprotect::foo;
}
};
template<typename T>
class Bar
{
public:
static void bar(T& self){(self.*Unprotect<Foo>::GetFooPtr())();}
};
int main()
{
Foo f;
Bar<Foo>::bar(f);
}
You did your friend declaration in the wrong direction. If Bar says Foo is it's friend, that means Foo gets access to Bar's private data. For Bar to get access to Foo's private data, Foo has to say Bar is its friend.
template<typename T>
class Bar
{
public:
static void bar(T& self){self.foo();}
};
class Foo
{
protected:
void foo() {}
friend class Bar<Foo>;
};
void main()
{
Foo f;
Bar<Foo>::bar(f);
}
If you want to access a protected member a derived class of this, you can do it with the using keyword:
class A
{
protected:
void i_am_protected () {}
};
template <class T>
class B : public T
{
using T::i_am_protected;
void call_me ()
{
i_am_protected(); // OK.
this->i_am_protected(); // This compiles without the keyword.
}
};
If you need B to access a protected member of A when an object is passed to B, you need to declare B as a friend of A:
class A
{
template <class T>
friend
class B;
protected:
void i_am_protected () {}
};
template <class T>
class B : public T
{
void call_me (T& obj)
{
obj.i_am_protected(); // OK.
}
};