继承构造函数是否与C ++ 0x中的模板一起使用?

时间:2011-09-12 21:52:07

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

在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是构造函数是一个特例。事实上,似乎存在歧义:如果我在T中有一个名为B的方法,我试图在A中添加重载(这就是编译器如何解释这样的使用声明前C ++ 0x)?

2 个答案:

答案 0 :(得分:10)

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

  

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

     
      
  • 如果在嵌套名称指定者之后指定的名称(在C中查找时)是C的注入类名(第9条),或
  •   
  • 在作为成员声明的using声明(7.3.3)中,如果在nested-name-specifier之后指定的名称与标识符中的名称相同,或者是最后一个simple-template-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;
};

总结:

  • 上面的第一个子弹是一个语义规则 - 如果嵌套名称说明符后面的名称引用了注入的类名(B::Bmytype::B),那么它将被翻译为引用到构造函数。

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

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

答案 1 :(得分:7)

是的,从标准(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总是引用占位符,因此'using T :: T'总是引用模板参数。