i have a class template roundtrip
which takes two policies. as long as they are different, everything is fine, but using one policy twice leads to compilation errors.
Example:
#include <iostream>
class walk {
protected:
void move() {
std::cout<<"i'm walking."<<std::endl;
}
};
class car {
protected:
void move() {
std::cout<<"i'm driving in a car."<<std::endl;
}
};
template<typename S, typename T>
class roundtrip : private S, private T {
public:
void printSchedule(void) {
std::cout<<"away: ";
S::move();
std::cout<<"return: ";
T::move();
}
};
int main(void){
roundtrip<walk,car> LazyTrip;
LazyTrip.printSchedule();
roundtrip<car,car> VeryLazyTrip; // ERROR: error: duplicate base type ‘walk’ invalid
VeryLazyTrip.printSchedule();
return 0;
}
how can that be resolved? or is there a better design to achieve the same behaviour?
EDIT: i added wrappers to the policies, the user interface does not change. what do you think about this solution, is it a clean design?
template<typename T>
class outbound : private T {
protected:
void moveOutbound(void) {
T::move();
}
};
template<typename T>
class inbound : private T {
protected:
void moveInbound(void) {
T::move();
}
};
template<typename S, typename T>
class roundtrip : private outbound<S>, private inbound<T> {
public:
void printSchedule(void) {
std::cout<<"away: ";
this->moveOutbound();
std::cout<<"return: ";
this->moveInbound();
}
};
Instead of inheriting, you could add data members to roundtrip
, but the functions in walk
and car
are currently protected
. If you cannot make the functions in walk
and car
public, you could:
befriend the roundtrip
template
class walk {
protected:
void move() {
std::cout<<"i'm walking."<<std::endl;
}
template<class T, class S>
friend class roundtrip;
};
make the member functions accessible to roundtrip
via a helper class:
template<typename S, typename T>
class roundtrip {
private:
struct helperT : private T
{
public: // or private + friend roundtrip
using T::move;
using T::T;
} mT;
struct helperS : private S
{
public:
using S::move;
using S::S;
} mS;
public:
void printSchedule(void) {
std::cout<<"away: ";
mT.move();
std::cout<<"return: ";
mS.move();
}
};
If the interface is the same for both types, you could use a helper class template instead of two helper classes:
template<typename S, typename T>
class roundtrip {
private:
template<class U>
struct helper : private U
{
public: // or private + friend roundtrip
using U::move;
using U::U;
};
helper<S> mS;
helper<T> mT;
public:
void printSchedule(void) {
std::cout<<"away: ";
mT.move();
std::cout<<"return: ";
mS.move();
}
};
(it is also possible to inherit from a helper template specialization, e.g. class roundtrip : helperT<T>, helperS<S>
)