Есть ли эквивалент <? расширяет T>, <? супер T> в C ++? - PullRequest
17 голосов
/ 27 ноября 2009
  1. Есть ли эквивалент C <? extends T>, <? super T> в C ++?

  2. Кроме того, <? extends T>, <? super T> работает, даже если T является интерфейсом в Java?

Ответы [ 6 ]

13 голосов
/ 27 ноября 2009

Он не имеет достаточно хорошего синтаксического сахара, как в Java, но хорошо справляется с boost / type_traits . См. http://www.boost.org/doc/libs/1_40_0/libs/type_traits/doc/html/index.html для получения дополнительной информации.

#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>

class Base {};
class Derived_from_Base : public Base {};
class Not_derived_from_Base {};

template<typename BASE, typename DERIVED>
void workOnBase()
{
    BOOST_STATIC_ASSERT((boost::is_base_of<BASE, DERIVED>::value)); 
}

int main()
{
    workOnBase<Base, Derived_from_Base>();     // OK
    workOnBase<Base, Not_derived_from_Base>(); // FAIL
    return 0;
}

1> d: ... \ main.cpp (11): ошибка C2027: использование неопределенного типа 'boost :: STATIC_ASSERTION_FAILURE' 1> с 1> [ 1> х = ложь 1>]

6 голосов
/ 27 ноября 2009

Чтобы ответить на ваш второй вопрос: да.Что касается дженериков, то интерфейсы обрабатываются так же, как и реальные классы.

Я оставлю первый вопрос более опытным людям на C ++.

3 голосов
/ 27 ноября 2009

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

Обычно это не так. Причина, по которой синтаксис существует в Java и C #, заключается в том, что они используют шаблоны, а не шаблоны.

Обобщения Java генерируют общий код, который использует виртуальную диспетчеризацию из базового типа, а не генерирует код для каждого типа, используемого в качестве аргумента шаблона. Поэтому обычно вы используете ограничение, чтобы позволить вам вызывать методы для объектов типа, используемого в качестве параметра шаблона.

Поскольку C ++ генерирует код для каждого типа, используемого в качестве параметра шаблона, ему не нужно знать о базовом типе для них.

Например, шаблонный класс для матрицы будет использовать операторы +, -, * для своего целевого типа. Затем может использоваться для любого типа, который поддерживает эти операторы. Если он был произвольно ограничен double с и int с, то вы не могли бы использовать шаблон с complex<double> или запустить тест с типом, который поддерживает интервальную арифметику, даже если эти типы предоставляют эти операторы, и библиотека матриц будет действительна при их использовании.

Способность работать с произвольными типами, которые имеют одинаковую форму, является силой шаблонов и делает их более полезными. Клиентский код должен решить, допустимо ли использовать этот шаблон с этим типом (пока он компилируется), и клиент всегда прав. Невозможность работать с произвольными типами, имеющими одинаковую форму, и требование указывать ограничения для вызова методов, отличных от java.lang.Object, является слабостью обобщений.

3 голосов
/ 27 ноября 2009

ответ на первую часть: Ограничить функцию шаблона

JesperE имеет право ответить на 2 часть.

2 голосов
/ 30 ноября 2015

Это сработало для меня:

#include <iostream>

class MyBase {}; 
class A : public MyBase {};    
class B {};

template <class T>
typename std::enable_if<!std::is_base_of<MyBase, T>::value>::type
Foo(T &v) {
    std::cout << "Foo 1" << std::endl;
}

template <class T>
typename std::enable_if<std::is_base_of<MyBase, T>::value>::type
Foo(T &v) {
    std::cout << "Foo 2" << std::endl;
}

int main() {
  A a;
  B b;
  Foo(a);
  Foo(b);
  return 0;
}
2 голосов
/ 27 ноября 2009

Это расширение , которое, к сожалению, было удалено из проекта стандарта C ++ 0x, так как оно "не было готово". Тем не менее, можно смоделировать это, используя статические утверждения (это часть C ++ 0x и Boost, как люди упоминали здесь).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...