微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C dynamic_cast转发声明的类模板编译,但它是安全的吗?

以下代码编译并给出结果(GCC和clang):
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 { }
};

代码将派生到Base中的foo到foo的调用.

作为参考,以下代码不编译:

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
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 …

这似乎表明第一个例子是不合法的.这是建构不良的吗?如果是这样,为什么我没有得到错误

解决方法

编辑:经过一点思考:模板首先得到定义,如果你实例化它们.所以你的第一个代码的工作原理找到原因,如果编译器已经达到了实例化模板类的行,首先定义模板.

原文地址:https://www.jb51.cc/c/115873.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐