my problem is a little bit weird and I'm not able to find an answer to it.
1) I do have a nested template class for my protocol
template <template<class TMessage> class TFrame, class TMessage>
class Protocoll
{
...
}
2) I do have an implementation for my frame and message
class MessageImpl : public Message
{
...
}
class FrameImpl : public Frame<MessageImpl>
{
...
}
3) Now I want to implement my protocol using the implementations for frame and message.
class ProtocolImpl : public Protocol<FrameImpl, MessageImpl>
{
...
}
The compiler complains about the first template Parameter "FrameImpl", because it is (obviously) no generic template type any more.
Is there any possibility to make this compile?
I don't want to make my 'FrameImpl' generic/template because than I would need to implement it in the header.
Thanks a lot
Edit:
Because of requesting a complete sample:
//--------------------- definitions
class Message
{
public:
virtual ~Message() = default;
virtual void foo() noexcept = 0;
};
template <class Message>
class Frame
{
public:
virtual ~Frame() = default;
virtual void foo() noexcept = 0;
};
template <template<class TMessage> class TFrame, class TMessage>
class Protocol
{
public:
virtual ~Protocol() = default;
virtual void foo() noexcept;
};
//--------------------- implementations
class MessageImpl : public Message
{
public:
void foo() noexcept
{ }
};
class FrameImpl : public Frame<MessageImpl>
{
public:
FrameImpl()
: message{ }
{ }
void foo() noexcept
{
message.foo();
}
private:
MessageImpl message;
};
class ProtocolImpl : public Protocol<FrameImpl, MessageImpl>
{
};
in the declaration of "ProtocolImpl", I could pass Frame as template type, but not FrameImpl.
You can do
template <typename>
using FrameImplT = FrameImpl;
class ProtocolImpl : public Protocol<FrameImplT, MessageImpl>
{
// ...
};
But think at what is the purpose of those template parameters.
Related
I am writing Interface and Invoker class that allows a class to be several type of invoker and several type of interface.
I don't manage to fix ambiguities in compilation when the function have no parameters ( so all versions have same signature ).
I tried to templatize the function so I can specialize when calling, but It still not removing the ambiguities.
I Know there several article here that talk about similar issue, but they are all with a parameter in the method so the signature is different for each specialization which remove the ambiguity.
I wrote a sample project as small as possible to show.
The workaround for the function Invoker::Interfaces is to add a parameter in the function, and they I can call with (IMyInterface*)0 , but this is ugly .
The workaround for the function Invoker::Register, is to static cast the parameter, but with a template it should find automatically the type of the parameter and I shouldn't need that.
Some help would be very grateful. So I could remove those ugly workarounds.
Thanks a lot.
Here the sample code.
template interface base class
template <class INVOKER>
class Interface
{
public:
INVOKER& Invoker() { return *m_invoker; }
private:
template <typename> friend class Invoker;
INVOKER* m_invoker;
};
template Invoker base class:
template <class INTERFACE>
class Invoker
{
public:
template<class I>
void Register(INTERFACE* _interface) { m_interfaces.push_back(_interface); }
void Register(INTERFACE* _interface) { m_interfaces.push_back(_interface); }
std::vector<INTERFACE*> Interfaces() { return m_interfaces; }
std::vector<INTERFACE*> Interfaces(INTERFACE*) { return m_interfaces; }
template<class I>
std::vector<INTERFACE*> Interfaces() { return m_interfaces; }
private:
std::vector<INTERFACE*> m_interfaces;
};
A short as possible of multi inheritance usage:
class DogLover;
class InterfaceDog : public Interface<DogLover>
{
public:
virtual bool AskIfGoodBoy() = 0;
};
class CatLover;
class InterfaceCat : public Interface<CatLover>
{
public:
virtual void Pet() = 0;
};
class DogLover : public Invoker<InterfaceDog> {};
class CatLover : public Invoker<InterfaceCat> {};
class PetLover
: public DogLover
, public CatLover
{
public:
using DogLover::Register;
using DogLover::Interfaces;
using CatLover::Register;
using CatLover::Interfaces;
int Size() { return m_size; }
void DoStuff()
{
for (InterfaceDog* interface : Interfaces((InterfaceDog*)0))
{
interface->AskIfGoodBoy();
}
/*
for (InterfaceCat* interface : Interfaces<InterfaceCat>()) << ambigous
{
interface->Pet();
}*/
}
private:
int m_size = 0;
};
class PetOwner
: public InterfaceCat
, public InterfaceDog
{
//using InterfaceDog::Invoker;
//using InterfaceCat::Invoker;
void Pet() override { /* Invoker().Size(); */}
bool AskIfGoodBoy() override { return true; }
};
Main :
int main()
{
PetLover petLover;
PetOwner petOwner;
//petLover.Register<DogLover>(&petOwner); // << ambigous
//petLover.Register<CatLover>(&petOwner); // << ambigous
petLover.Register(static_cast<InterfaceDog*>(&petOwner));
petLover.Register(static_cast<InterfaceCat*>(&petOwner));
}
Thanks to #fabian (https://stackoverflow.com/users/2991525/fabian)
I forgot the obvious simplest solution :) which it to specify the class which from you want to call the method like this
Interface:
for (InterfaceCat* interface : CatLover::Interfaces())
{
interface->Pet();
}
Register:
petLover.DogLover::Register(&petOwner);
petLover.CatLover::Register(&petOwner);
Invoker:
class PetOwner
: public InterfaceCat
, public InterfaceDog
{
void Pet() override
{
InterfaceDog::Invoker().Size();
}
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); }
};
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);
}
Say I've got the following (pseudo-)code:
class base{
public:
virtual void callMe() = 0;
virtual void doRender() = 0;
}
class a : public base{
public:
virtual void callMe(){/*doA*/} override;
}
class b : public base{
public:
virtual void callMe(){/*doB*/} override;
}
class myClass : public base, public a, public b{
public:
virtual void doRender(){
this->a::callMe();
this->b::callMe();
} override;
}
Would there be a way to write this differently? Something like:
class myClass : public base, public a, public b{
public:
virtual void doRender(){
this->allSupers::callMe();
} override;
}
My goal with this would be to have a base class that can be extended to have different "features", all of which have to be executed on doRender.
I know I could of course keep track of these functions by means of a function pointer list in base, in which the subclasses put their own functions when constructed, but I'd like to avoid that. Having to iterate over these functions still gives me at least three lines of code in my final doRender. (Or one long unreadable line.)
I'm open for suggestions using templates.
Depending on you actual problem at hand, you might be able to use the mixin-style. Essentially you can have each class call the next callMe at the end (or begining) of their own callMe. One benefit is that callMe does not need to be a virtual function. Here is a minimal example (online):
#include <iostream>
class base
{
public:
void callMe() {}; // Empty base case
virtual void doRender() = 0;
};
template <class super>
class a : public super
{
public:
void callMe()
{
std::cout << "doA" << '\n';
super::callMe(); // Call the next
};
};
template <class super>
class b : public super
{
public:
void callMe()
{
std::cout << "doB" << '\n';
super::callMe(); // Call the next
};
};
template <class super>
class myClass_t : public super
{
public:
void doRender()
{
super::callMe();
};
};
using myClass = myClass_t<a<b<base> > >; // Defining the order of evaluation;
int main()
{
myClass m;
m.doRender();
}
With variadic template, you may do:
template <typename ... Ts>
class myClassTs : public base, public Ts...
{
public:
virtual void doRender(){
int dummy[] = {0, (Ts::callMe(), void(), 0)...};
static_cast<void>(dummy); // Silent warning for unused variable
} override;
}
using myClass = myClassTs<a, b>;
And in C++17, it would be
template <typename ... Ts>
class myClassTs : public base, public Ts...
{
public:
virtual void doRender(){
(static_cast<void>(Ts::callMe()), ...);
} override;
}
Given the following:
class Observer
{
public:
virtual void Observe(Parameter p) = 0;
};
template<size_t Tag>
class TaggedObserver : public Observer { };
class Thing : public TaggedObserver<0>, TaggedObserver<1>
{
public:
virtual void Observe(Parameter p) override;
};
Thing::Observe overrides both TaggedObserver<0>::Observe and TaggedObserver<1>::Observe.
Is there a way to provide a different override for each base class?
Rationale: I want the class to be able to observe two notification sources of the same type with different actions for each source without having to resort to pass the source in the parameter and then checking it in an if/switch.
In order to provide different overrides, you need to define different derived classes, eg:
class Observer
{
public:
virtual void Observe(Parameter p) = 0;
};
template<size_t Tag>
class TaggedObserver : public Observer
{
};
class TaggedObserverZero : public TaggedObserver<0>
{
public:
virtual void Observe(Parameter p)
{
// do something ...
}
};
class TaggedObserverOne : public TaggedObserver<1>
{
public:
virtual void Observe(Parameter p)
{
// do something else ...
}
};
However, if you want Thing::Observe() to receive the Parameter first and dispatch it to the appropriate base class, you can't avoid using an if statement (or equivalent) in Thing, since it inherits multiple copies of TaggedObserver::Observe() and needs to decide which one to call:
class Thing : public Observer, TaggedObserverZero, TaggedObserverOne
{
public:
virtual void Observe(Parameter p)
{
if (some condition)
TaggedObserverZero::Observe(p);
else if (some other condition)
TaggedObserverOne::Observe(p);
}
};
Or, you call just them both unconditionally and let them figure out what to do:
class TaggedObserverZero : public TaggedObserver<0>
{
public:
virtual void Observe(Parameter p)
{
if (some condition)
// do something ...
}
};
class TaggedObserverOne : public TaggedObserver<1>
{
public:
virtual void Observe(Parameter p)
{
if (some other condition)
// do something else ...
}
};
class Thing : public Observer, TaggedObserverZero, TaggedObserverOne
{
public:
virtual void Observe(Parameter p)
{
TaggedObserverZero::Observe(p);
TaggedObserverOne::Observe(p);
}
};
Implement them in TaggedObserver (provide explicit specialization if needed), as an example:
class Observer {
public:
virtual void Observe(Parameter p) = 0;
};
template<size_t Tag>
class TaggedObserver : public Observer {
public:
void Observe(Parameter p) override { }
};
template<std::size_t... I>
class Thing : public TaggedObserver<I>... {
public:
Thing(): TaggedObserver<I>{}... {}
template<std::size_t N>
void Observe(Parameter p) {
TaggedObserver<N>::Observe(p);
}
};
Then, you can specialize Thing as Thing<0, 1> and invoke the right function using thing.Observe<1>(p).
EDIT
The purpose of this edit is to show a new example code, that is more or less the one above even if slightly modified.
I hope this can help the OP. The basic idea is to combine CRTP idiom, virtual methods and inheritance.
class Observer {
public:
virtual void Observe(Parameter p) = 0;
};
template<template T, size_t Tag>
class TaggedObserver : public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
}
};
template<std::size_t... I>
class Thing : public TaggedObserver<Thing<I...>, I>... {
template<std::size_t J>
friend class TaggedObserver<Thing<I...>, J>;
public:
Thing(): TaggedObserver<Thing<I...>, I>{}... {}
template<std::size_t N>
void Observe(Parameter p) {
TaggedObserver<Thing<I...>, N>::Observe(p);
}
};
Note that the friend declaration allows TaggedObservers to access private members of Thing.
This way, implementations of Observe in TaggedObservers can access public, protected and private members from Thing, as requested in the comments.
Finally you can specialize TaggedObserver if needed, so as to provide different implementations for Observe.
As an example:
template<template T, size_t Tag>
class TaggedObserver;
template<template T>
class TaggedObserver<T, 0>: public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
// Put here the code of the specialization for Tag 0
}
};
template<template T>
class TaggedObserver<T, 1>: public Observer {
public:
void Observe(Parameter p) override {
T *t = static_cast<T*>(this);
// Now use whatever you want from T, that is Thing in this example
// Put here the code of the specialization for Tag 1
}
};