I want to create a overloaded operator<<
for a template base class, that calls the toString
function for the child class. The issue is that the toString
function of the child class is constexpr
, which mean I cannot make it a virtual function of the base class. Here is what I want to do:
template<typename T>
class Base {
public:
Base(const T& t) : m_val(t) {}
friend std::ostream & operator<<(std::ostream &os, const Base& base);
protected:
const T m_val;
};
class Child1 : public Base<SomeLiteralType1> {
public:
using Base::Base;
constexpr const char* toString() {
const char* LUT[] = {"aa", "bb"};
return LUT[m_val]; // <-- assume T can be converted to int
}
};
class Child2 : public Base<SomeLiteralType2> {
...
};
std::ostream & operator<<(std::ostream &os, const Base& base) {
// cannot access toString() since it is not defined in Base
// maybe using dynamic_cast?
}
int main() {
Child1 c1 = {...};
Child2 c2 = {...};
// I want to be able to use << directly:
std::cout<<c1<<std::endl;
std::cout<<c2<<std::endl;
}
Use CRTP to get access to the derived class:
template <typename T, typename Derived>
class Base {
...
friend std::ostream& operator<<(std::ostream& os, const Base& base) {
return os << static_cast<const Derived&>(base).toString();
}
...
};
class Child1 : public Base<int, Child1> {
...
};