【问题标题】:Does inheriting constructors work with templates in C++0x?继承构造函数是否适用于 C++0x 中的模板?
【发布时间】:2011-11-15 16:58:37
【问题描述】:

在 C++0x 中,您可以使用 using 关键字来继承构造函数,如下所示:

class B { B(int) {} };

class A : public B { using B::B; };

这将隐式声明A(int) 构造函数。这适用于模板吗?

class B { B(int) {} };

template<class T> class A : public T { using T::T; };

T::T 内,我希望编译器能够找出左手T,因为在模板参数上使用范围运算符是正常的,但找出右手T 是构造函数是一种特殊情况。事实上,似乎存在歧义:如果我在B 中有一个名为T 的方法,我试图在A 中添加重载(这就是编译器如何解释这样的 using 声明 pre-C+ +0x)?

【问题讨论】:

    标签: c++ inheritance constructor standards c++11


    【解决方案1】:

    是的,从标准(2011 年 2 月草案)第 12.9 节看来确实如此:

    template< class T >
    struct D : T {
    using T::T; // declares all constructors from class T
    ~D() { std::clog << "Destroying wrapper" << std::endl; }
    };
    

    类模板 D 包装任何类并转发其所有构造函数, 在向标准日志写入一条消息时,只要一个对象 D级被摧毁。 ——结束示例

    另外需要注意的是,虽然标准允许,但根据this list,只有 1 个编译器 IBM XLC++ 在发布版本中支持此功能。 GCC 目前仅通过补丁支持它。

    编辑:AJG85 指出模板中的 T 始终指代占位符,因此“使用 T::T”始终指代模板参数。

    【讨论】:

    • 不,那很好,因为typename T 不代表名为 T 的方法,它代表模板实例化使用的类型符号的占位符。例如A&lt;int&gt; 会导致using int::int; ... 警告词:如果类型不是像 STL 容器这样的基类,会发生什么情况?
    • 您在成员变量问题上是正确的。至于 STL 容器的继承,它会起作用,但如果您要以多态方式使用该类型,您将面临风险。但是,如果您只是创建 D >,然后在一个地方像这样使用它,那么它会起作用。这不是一个好的做法,但它会起作用。
    • 正确,但一定要牢记,因为向派生对象添加状态或使用基类指针可能会被意外引入,因为模板在某种程度上混淆了后续问题的继承和根本原因。跨度>
    【解决方案2】:

    是的,它有效,原因是名称查找机制。继承构造函数声明的工作机制很简单:如果 using 声明的名称引用基类构造函数,那就是继承构造函数声明。在 3.4.3.1[class.qual]p2 我们发现:

    在构造函数是可接受的查找结果且嵌套名称说明符指定类 C 的查找中

    • 如果在嵌套名称说明符之后指定的名称,当在 C 中查找时,是 C 的注入类名称(第 9 条),或者
    • 在作为成员声明的 using-declaration (7.3.3) 中,如果在嵌套名称说明符之后指定的名称与最后一个标识符或简单模板 ID 的模板名称相同嵌套名称说明符的组成部分

    该名称被认为是命名类 C 的构造函数。

    这是使类构造函数定义起作用的段落,也是使继承构造函数声明起作用的段落。第二个项目符号适用于这种情况:

    struct B {
      B(int) { }
    };
    
    typedef B mytype;
    
    struct A : B {
      // "name ... is the same as the identifier ... in the last component ..."
      using mytype::mytype;
    };
    
    
    template<typename T> using same = T;
    
    struct C : B {
      // "name ... is the same as the template-name ... in the last component ..."
      same<B>::same;
    };
    

    后一个例子证明在以下情况下也很有用

    template<template<typename> class Base>
    struct X : Base<int> {
      using Base<int>::Base;
    };
    

    总结:

      1234563 s)。
    • 第二个项目符号是句法规则-名称必须匹配-否则它们的含义无关紧要-在提供给X的模板参数中可能有一个名为Base的成员,如下所示,但是using 声明仍将导入构造函数并且将成员命名为Base:

      template<typename T> struct D { private: T Base; };
      X<D> x; // valid, the private member is *not* touched!
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 2013-01-24
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 2012-04-18
      • 2019-12-14
      相关资源
      最近更新 更多