CRTP 为什么是成员查找运行时?

CRTP why is member lookup runtime?

或者至少我认为是。 考虑以下代码

#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;
}

我希望编译器足够好,可以在 doFoo 的编译时检查 foo 的存在,但在这两种情况下,virtual 在基础中,而没有virtual 在 base 中,代码编译得很好,但在运行时崩溃。

这是为什么?

编辑:clang 设置

clang version 4.0.1 (tags/RELEASE_401/final)
Target: x86_64-unknown-linux-gnu 

doFoo<Unrelated>()注释掉编译。

和 g++ 设置

gcc version 7.1.1 20170630 (GCC) 

编译时 doFoo<Unrelated>() 已注释掉。

这是因为两个 classes 都有一个名为 foo 的函数。每个 class.

都存在于基数 class 中

然而,该函数所做的只是调用自身,这最终会导致堆栈溢出。