下面的代码用g ++编译好,但不能用clang ++(3.6)编译:
// Forward declaration:
template <class S, class T>
struct Base;
template <class T>
struct BaseFriend {
friend struct Base<int, T>;
};
// Actual declaration:
template <class S, class T = int>
struct Base {
void foo() {}
};
struct DerivedFriend : BaseFriend<int> {};
struct Derived : Base<int> {
void foo(int) {
Base<int>::foo();
}
};
Run Code Online (Sandbox Code Playgroud)
Derived::foo定义中出错:
error: too few template arguments for class template 'Base'
Base<int>::foo();
^
test.cpp:3:8: note: template is declared here
struct Base;
^
Run Code Online (Sandbox Code Playgroud)
经过一些小修复后,错误消失了,例如: …
请考虑以下示例:
class Base {
public:
int data_;
};
class Derived : public Base {
public:
void fun() { ::std::cout << "Hi, I'm " << this << ::std::endl; }
};
int main() {
Base base;
Derived *derived = static_cast<Derived*>(&base); // Undefined behavior!
derived->fun();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据C++标准,函数调用显然是未定义的行为.但是在所有可用的机器和编译器(VC2005/2008,RH Linux和SunOS上的gcc)上,它按预期工作(打印"嗨!").有谁知道配置此代码可以正常工作?或者可能是具有相同想法的更复杂的例子(注意,Derived不应该携带任何额外的数据)?
更新:
从标准5.2.9/8:
类型"指针CV1 B",其中B是一个类类型的右值,可以转换为类型"指针CV2 d",的右值,其中d是从乙派生的类(第10节),如果一个有效的标准从"指针d"转换到"指针到B"的存在(4.10),CV2是相同cvqualification为或者更大cvqualification比,CV1,和B不是虚拟基类d的空指针值(4.10)转换为目标类型的空指针值.如果类型是"指针CV1 B"点右值进行B实际上是类型d的对象的子对象,将所得指针指向类型D.的包围对象否则,铸造的结果是不确定的.
还有一个9.3.1(感谢@Agent_L):
如果为非X类型的对象或从X派生的类型调用类X的非静态成员函数,则行为未定义.
谢谢,迈克.