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 中
然而,该函数所做的只是调用自身,这最终会导致堆栈溢出。
或者至少我认为是。 考虑以下代码
#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 中然而,该函数所做的只是调用自身,这最终会导致堆栈溢出。