Подтвердить что ты не робот

Работает ли наследование конструкторов с шаблонами в С++ 0x?

В С++ 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 перегрузки (что как компилятор интерпретирует такое использование объявления pre-C + + 0x)?

4b9b3361

Ответ 1

Да, это работает, и причина - механизм поиска имени. Механизм объявления наследования-конструкторов прост: если имя используемого объявления относится к конструкторам базового класса, это объявление наследования конструкторов. В 3.4.3.1 [class.qual] p2 находим:

В поиске, в котором конструктор является приемлемым результатом поиска, а спецификатор вложенных имен назначает класс C

  • если имя, указанное после вложенного имени-спецификатора, при поиске на C, является введенным классом-именем C (раздел 9) или
  • в декларации using (7.3.3), которая является объявлением-членом, если имя, указанное после спецификатора вложенных имен, совпадает с идентификатором или именем шаблона-шаблона в последнем компонент спецификатора вложенных имен

вместо этого вместо имени будетменоваться конструктор класса 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::B или mytype::B), тогда оно будет переведено на ссылку на конструктор ( с).

  • Вторая пуля - это синтаксическое правило - имена должны просто совпадать - их значение не имеет значения в противном случае - в аргументе шаблона, предоставленном X, может быть член с именем Base, например, в следующее, но объявление using все равно будет импортировать конструкторы и не называть элемент Base:

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

Ответ 2

Да, похоже, что это делается из стандарта (февраль 2011 г.), раздел 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 уничтожается. -end пример

Еще одна вещь, которую следует отметить, в то время как стандарт позволяет это, согласно этот список, только 1 компилятор IBM XLС++ поддерживает эту функцию в релиз. GCC только в настоящее время поддерживает его с патчем.

Изменить: AJG85 указал, что T в шаблоне всегда ссылается на placeholder, поэтому "использование T:: T" всегда ссылается на аргумент шаблона.