template <typename T> struct Derived; struct Base { template <typename T> void foo(T * const t) { dynamic_cast<Derived<T> * const>(this)->bar(t); } }; template <typename T> struct Derived : Base { void bar(T const *) const { } };
作为参考,以下代码不编译:
struct Derived2; struct Base2 { template <typename T> void foo(T * const t) { dynamic_cast<Derived2 * const>(this)->bar(t); } }; struct Derived2 : Base2 { template <typename T> void bar(T const *) const { } };
GCC提供以下诊断:
main.cpp: In member function 'void Base2::foo(T*)': main.cpp:126:45: error: invalid use of incomplete type 'struct Derived2' dynamic_cast<Derived2 * const>(this)->bar(t); ^ main.cpp:119:8: note: forward declaration of 'struct Derived2' struct Derived2; ^
C14标准在“一体化规则”一节中规定如下:
5 Exactly one definition of a class is required in a translation unit
@H_502_36@
if the class is used in a way that requires the class type to be
complete.
[ Example: the following complete translation unit is
well-formed,even though it never defines X:
struct X; // declare X as a struct type
struct X* x1; // use X in pointer formation
X* x2; // use X in pointer formation
—end example ]
[ Note: The rules for
declarations and expressions describe in which contexts complete class
types are required. A class type T must be complete if:
(5.1) — an object of type T is defined (3.1),or
(5.2) — a non-static class data member of type T is declared (9.2),or
(5.3) — T is used as the object type or array element type in a new-expression (5.3.4),or
(5.4) — an lvalue-to-rvalue conversion is applied to a glvalue referring to an object of type T (4.1),or
(5.5) — an expression is converted (either implicitly or explicitly) to type T (Clause 4,5.2.3,5.2.7,5.2.9,5.4),or
(5.6) — an expression that is not a null pointer constant,and has type other than cv void*,is converted to the type pointer to T or reference to T using a standard conversion (Clause 4),a dynamic_cast (5.2.7) or a static_cast (5.2.9),or …这似乎表明第一个例子是不合法的.这是建构不良的吗?如果是这样,为什么我没有得到错误?