Да, это работает, и причина кроется в механизме поиска имени.Механизм, в котором работает объявление наследующих конструкторов, прост: если имя используемого объявления ссылается на конструкторы базового класса, это объявление наследующих конструкторов.На 3.4.3.1 [class.qual] p2 мы находим:
В поиске, в котором конструктор является приемлемым результатом поиска, а спецификатор вложенного имени назначает класс C
- , если имя, указанное после спецификатора вложенного имени, при поиске в C, является именем введенного класса C (пункт 9) или
- в объявлении использования (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
), то оно будет преобразовано для ссылки на конструктор (ы).
Второй маркер является синтаксическим правилом - имена просто должны совпадать - в противном случае их значение не имеет значения - в аргументе шаблона, предоставленном * 1032, мог быть элемент с именем Base
*, например, как показано ниже, но объявление using все равно импортирует конструкторы и делает not имя члена Base
:
template<typename T> struct D { private: T Base; };
X<D> x; // valid, the private member is *not* touched!