-
Есть ли эквивалент
<? extends T>
,<? super T>
в С++? -
Кроме того, работает ли
<? extends T>
,<? super T>
, даже еслиT
является интерфейсом в Java?
Существует ли эквивалент <? расширяет T>, <? супер T> в С++?
Ответ 1
ответ на первую часть: Ограничить функцию шаблона
У JesperE есть ответ на вторую часть.
Ответ 2
В нем нет довольно приятного синтаксического сахара, как в 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: использование undefined type 'boost:: STATIC_ASSERTION_FAILURE' 1 > с 1 > [ 1 > x = false 1 > ]
Ответ 3
Чтобы ответить на второй вопрос: да. Что касается дженериков, интерфейсы обрабатываются так же, как и реальные классы.
Я оставлю первый вопрос более опытным людям С++.
Ответ 4
Вы можете ограничить диапазон параметра шаблона в С++, используя различные механизмы признаков, из которых есть возможности реализации в boost.
Обычно вы этого не делаете - причина, по которой синтаксис существует в Java и С#, заключается в том, что они используют generics, а не шаблоны.
Генераторы Java генерируют общий код, который использует виртуальную отправку из базового типа, а не генерирует код для каждого типа, используемого в качестве аргумента шаблона. Поэтому обычно вы используете ограничение, чтобы позволить вам вызывать методы для объектов типа, используемых в качестве параметра шаблона.
Поскольку С++ генерирует код для каждого типа, используемого в качестве параметра шаблона, ему не нужно знать о базовом типе для них.
Например, класс шаблона для матрицы будет использовать операторы +, -, * для целевого типа. In может затем использоваться для любого типа, который поддерживает эти операторы. Если бы это было произвольно ограничено double
и int
s, вы не могли бы использовать шаблон с complex<double>
или запустить тест с типом, который поддерживает арифметику интервалов, даже если эти типы предоставляют эти операторы, а матричная библиотека будет действительна с их использованием.
Возможность работать с произвольными типами, которые имеют одинаковую форму, является мощью шаблонов и делает их более полезными. Это до клиентского кода, чтобы решить, действительно ли это использовать этот шаблон с этим типом (пока он компилируется), и клиент всегда прав. Неспособность работать с произвольными типами, которые имеют одинаковую форму, а требование указывать ограничения на методы вызова, отличные от методов java.lang.Object
, является недостатком дженериков.
Ответ 5
Это расширение, которое, к сожалению, было удалено из черновика стандарта С++ 0x, поскольку оно "не было готово". Тем не менее, это можно моделировать с помощью статических утверждений (которые являются частью С++ 0x и Boost, как упоминалось здесь).
Ответ 6
Это сработало для меня:
#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;
}