jeudi 20 juillet 2017

CRTP why is member lookup runtime?

Or at least I think it is. Consider the following code

#include <iostream>
#include <memory>

struct BaseBase {
    virtual void foo() = 0;
    virtual ~BaseBase(){}
};

template <typename Derived>
struct Base : BaseBase{
    void foo() override{
        static_cast<Derived*>(this)->foo();
    }
};

struct D1 : Base<D1> {};
struct Unrelated {};

// no runtime polymorphism
template <typename SDerived>
struct SBase{
    void foo() {
        static_cast<SDerived*>(this)->foo();
    }
};

struct SD1 : SBase<SD1> {};


template <typename T, typename ...Args>
void doFoo(Args&&... args){
    T* t = new T(std::forward<Args>(args)...);
    t->foo();
}

int main(){
    doFoo<Unrelated>(); //compile time error, foo not found in unrelated
    doFoo<SD1>(); //runtime crash
    doFoo<D1>(); //runtime crash
    return 0;
}

I was hoping the compiler would be nice enough to check for the existence of fooat compile time in doFoo but in both cases, with virtual in base, and without virtual in base the code compiles just fine but crashes at runtime.

Why is this?

Aucun commentaire:

Enregistrer un commentaire