Унаследованный конструктор c ++ 0x в шаблонах
-
29-10-2019 - |
Вопрос
Вот класс foo:
общийВот панель класса:
общийПравильный ли синтаксис для наследования конструкторов?Если я использую "using foo :: foo;"тогда компилятор Visual C ++ 2010 умирает. Итак, как наследовать конструкторы из классов шаблонов в VC ++ 2010?
Решение
Чтобы этот синтаксический анализ был правильным, вам нужно вставить template
перед foo<T>;
, чтобы сообщить компилятору, что foo
следует рассматривать как имя шаблона (он не может заглядывать в foo<T>
, чтобы сказать себя, поскольку код T
неизвестен). Но использование кода ::template
в объявлении using запрещено. Имя также не относится ко всем конструкторам bar
: вместо этого оно будет относиться к определенной специализации шаблона функции конструктора (T
является аргументом шаблона) такого конструктора следующим образом
Кроме того, для объявления using недопустимо использовать код template-id
(например, foo<T>
) в качестве своего имени (что, по сути, запрещает ему ссылаться на специализацию шаблона функции, с добавлением запрета на указание специализаций шаблона функции преобразования имен) ), поэтому даже если вы исправите проблему синтаксического анализа с помощью ::template
(если это будет возможно), вы все равно получите ошибку на этом этапе.
Когда были введены унаследованные конструкторы, были добавлены специальные правила, которые позволяют ссылаться на конструктор с помощью синтаксического правила: если у вас есть квалифицированный идентификатор (который в основном является квалифицированным именем с использованием кода ...::...
), и последнее уточненное имя перед окончательными именами частей конкретный класс, то вы можете обозначить конструктор (ы) этого класса двумя дополнительными способами:
- Если класс был назван с использованием идентификатора шаблона (имя формы
foo<T>
), а последняя часть соответствует имени шаблона (то есть,foo<T>::foo
илиTTP<T>::TTP
сTTP
является параметром шаблона шаблона). - Если последняя часть соответствует имени класса (например,
foo::foo
илиT::T
, при этомT
является параметром шаблона).
Эти два дополнительных правила активны только в объявлении using. И их, естественно, не было в C ++ 03. Другое правило, которое также присутствовало в C ++ 03: если последняя часть называет имя внедренного класса, то это полное имя также относится к конструктору:
- Сгенерировать кодовый код будет работать. Но только с этим правилом
foo::foo
(гдеT::T
обозначает классT
) не будет работать, потому чтоfoo
не имеет члена с именемfoo
.
Поэтому, имея особые правила, вы можете писать
общий Второе тоже верно: T
- это имя внедренного класса, которое было внедрено в foo
базового класса и унаследовано от foo<T>
. Мы ссылаемся на это имя с помощью bar
, а затем добавляем последнюю часть bar::foo
, которая снова ссылается на имя внедренного класса, чтобы обозначить конструктор (ы) `foo.
Теперь вы понимаете, почему начальное имя, которое вы пробовали, могло бы относиться к специализации шаблона функции конструктора (если бы это было разрешено): потому что часть foo
будет называть все конструкторы, а foo<T>::foo
, который последует за этим, затем отфильтрует шаблон и передать аргумент типа.
Другие советы
Если ваш компилятор еще не поддерживает наследование конструкторов, но поддерживает макросы с переменным числом аргументов, шаблоны с переменным числом значений и ссылки на rvalue, а также действительно удобную функцию type_trait, вот действительно достойный обходной путь:
родовое словоЕсли у вас еще нет is_constructible, основная идея работает и без него, но «унаследованный конструктор» будет слишком жадным.
вам не нужен второй параметр шаблона;
родовое словоследует делать
edit Я утверждаю, что это работает на g ++ - 4.4.1, однако это должен быть правильный синтаксис, когда функция станет доступной
В других ответах уже хорошо объясняется, как работают наследование конструкторов в C ++ 0x.Однако на момент написания этой статьи ни один компилятор не реализовал полностью весь набор функций C ++ 0x.К сожалению, это означает, что VC ++ 2010 еще не поддерживает наследующие конструкторы.
Стандарт C ++ 0x еще не опубликован.Окончательный вариант стандарта будет завершен где-то вМарт , но у ISO потребуется еще несколько месяцев, чтобы опубликовать его.В течение этого времени разработчики компилятора внедряют функции, поэтому они будут максимально совместимы с C ++ 0x, когда стандарт будет завершен.
Я считаю, что последняя версия GCC поддерживает наследование конструкторов, поэтому, если вам нужно попробовать его сейчас, вы можете использовать это.Конечно, поддержка C ++ 0x является экспериментальной и может изменяться по мере обнаружения ошибок и т. Д.