#include <iostream>
template<typename Impl>
struct renderer{
void get(){
static_cast<Impl*>(this)->get();
}
};
struct open_gl : public renderer<open_gl>{
void get(){
std::cout << "OpenGL" << std::endl;
}
};
struct direct_draw : public renderer<direct_draw>{
void get(){
std::cout << "DX" << std::endl;
}
};
template<typename T>
void print_renderer(renderer<T> r){
r.get();
}
int main() {
auto gl = open_gl();
auto dx = direct_draw();
print_renderer(gl);
print_renderer(dx);
}
Why can't I change the parameter of print_renderer to
void print_renderer(const renderer<T> &r)
?cannot convert 'this' pointer from 'const renderer<open_gl>' to 'renderer<open_gl> &'
`Why do I get a runtime error when I rename the method
get
in open_gl from get to get1? Shouldn't this trigger a compiler error?Error = Stack overflow
**Note I am using the latest MSVC
get
is not markedconst
.1) Because
get
is not aconst
member function : it cannot make the promise of not modify your (const) argument.You could declare
get
asconst
, and it compiles fine :2) The base
get
method will be called, going into infinite recursion : Stack Overflow.If you declare your function
override
(it needs to be virtual), the compiler will throw an error if it does not indeed override a base method :Note:
The title is "Static polymorphism in C++", but I think that you misunderstood what is static polymorphism : it does not (have to) make use of inheritance (as you did). Rather, the templates compile-time duck typing will statically "resolve" function calls for you.
That is, you don't need related types, you don't need the base
renderer
class at all, and you can simply do the following (in which case, renaming toget1
will cause a compiler error) :Live demo