Эквивалентно `<T extends MyClass>` в C++

В Java вы можете определить общий тип, который должен пересекаться с другим, с помощью <T extends MyClass> void myMethod(T item)

Есть ли аналог в cpp? Я пробовал template<class T : Draw_Shape> class MyClass, но не работает.

шаблоны и дженерики — совсем другая история. С шаблонами вы можете просто template <typename T> void myMethod(T). Требование наследования от базы встречается довольно редко. Как правило, вам нужны операции, которые вам нужны для T (и поддерживает ли T их, потому что он наследуется от MyClass или каким-то другим способом, это не имеет значения)

463035818_is_not_a_number 25.12.2020 21:27

Нет, эквивалента нет. Вероятно, вам следует сосредоточить свой вопрос на том, чего вы хотите достичь, и показать пример кода.

super 25.12.2020 21:27

В C++17 и более ранних версиях можно использовать SFINAE для ограничения параметров шаблона. В C++20 и более поздних версиях также есть концепции, которые были бы ближе к Java extends. Обе эти темы относятся к достаточно сложным темам C++, и вы найдете дополнительную информацию и полное объяснение в своем учебнике по C++.

Sam Varshavchik 25.12.2020 21:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
3
407
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Читая ниже, имейте в виду, что я не программист Java. Мои знания Java почти полностью абстрактны и, возможно, устарели. Так что, реализовала ли Java овеществление дженериков в последней или двух последних версиях, я об этом не знаю.


Таким образом, шаблоны Java Generics и C++ имеют общий синтаксис и использование, но под капотом это очень разные вещи.

Java Generics — это оболочка автоматически написанных приведений и проверок типов во время компиляции вокруг одного основного типа.

С другой стороны, шаблоны C++ генерируют новые несвязанные типы для каждого набора аргументов шаблона.

Синтаксис extends MyClass в Java делает две вещи. Во-первых, это позволяет этому «основному» типу универсального знать, что T является не просто объектом, а на самом деле подклассом некоторого интерфейса. Это необходимо для типа "core" для безопасного использования методов (без динамических приведений типа "сбой во время выполнения").

В C++ этого не происходит, потому что нет "основного" типа, сгенерированного при создании экземпляра шаблона. Каждый экземпляр шаблона компилируется независимо, поэтому известно, допустимы операции или нет.

Во-вторых, он выдает ошибки типа, когда неправильный тип передается универсальному типу. Третье, что он делает, это позволяет Java проверять универсальный код на достоверность до его создания.

Во-вторых, C++ может использовать концепции (если ваш компилятор достаточно новый) или использовать метод, известный как SFINAE, который столь же мощен, но синтаксически ужасен, и, честно говоря, его способность решать эту проблему была случайностью при разработке языка (это случайно Тьюринг). полный).

Что касается третьего, проверенного шаблона на C++, он предлагался много раз, но постоянно сталкивается с проблемами производительности во время компиляции. Таким образом, нет способа сделать это на С++, кроме создания экземпляра шаблона.

Решения:

Ничего не делать:

Нет, серьезно. Используйте утиную печать и не ограничивайте параметры шаблона. Единственным большим недостатком являются уродливые сообщения об ошибках, и редко «операции с одним и тем же именем имеют разные значения».

static_assert:

template<class T> class MyClass{
  static_assert(std::is_base_of_v<Draw_Shape,T>);
};

это генерирует чистые сообщения об ошибках. Есть некоторые недостатки в том, что другой код не может проверить, является ли MyClass<X> допустимым экземпляром без серьезной ошибки компилятора.

СФИНАЭ:

template<class T,
  std::enable_if_t<std::is_base_of_v<Draw_Shape,T>, bool> =true
>
class MyClass{
};

обратите внимание, что =true не сравнивает тест со значением true. Это не ==true. То, что здесь происходит, смехотворно сложно и раздражает; использование SFINAE для этой цели - это хак, и это просто способ сделать его чистым.

Концепции:

template<class T> requires std::is_base_of_v<Draw_Shape,T>
class MyClass{
};

или

template<std::is_derived_from<Draw_Shape> T>
class MyClass{
};

обратите внимание, что для концепций требуется современный компилятор C++ и стандартная библиотека.

Поскольку вы упомянули концепции, возможно, стоит отметить std::derived_from<Draw_Shape> T. Это максимально близко к реальному синтаксису Java.

StoryTeller - Unslander Monica 25.12.2020 22:38

Другие вопросы по теме