Я хотел бы создать класс, в котором можно использовать любой вектор.
Возможными типами могут быть std::vector, boost::vector, etl::vector.
Все используемые векторные типы должны реализовывать функции-члены std::vector. Я хотел бы создать концепцию, которая подтверждает, что используемый векторный тип реализует все функции-члены std::vector
До сих пор я придумал
#include <concepts>
#include <vector>
template < typename T , typename Element_T>
concept IVector_T = requires(T vec, Element_T elem)
{
{vec.push_back(elem) } -> std::same_as<void>; ///< Add an element to the vector
{vec.back()} ->std::convertible_to<Element_T>;
};
template<typename Element_T, IVector_T Vector_T>
class TestVector
{
public:
void push_back(const Element_T& elem)
{
myVec.push_back(elem);
}
Element_T& back()
{
//return ref to last element
return myVec.back();
}
private:
Vector_T<Element_T> myVec;
};
Однако я получаю ошибку компилятора
<source>(27): error C2059: syntax error: '<'
<source>(28): note: see reference to class template instantiation 'TestVector<Element_T,Vector_T>' being compiled
<source>(27): error C2238: unexpected token(s) preceding ';'
<source>(19): error C3861: 'myVec': identifier not found
<source>(19): error C2065: 'myVec': undeclared identifier
Я использую последнюю версию MSVC17 на Win 10, однако она также должна работать на Linux и Mac.
У меня есть ссылка на Godbolt, чтобы вы могли легко воспроизвести эту проблему. https://godbolt.org/z/54zac583j
Спасибо за вашу помощь, ребята :)
Редактировать: Как отмечено в комментариях, pop_into() не является стандартным. => заменил его на back().
Чтобы уточнить: для некоторых векторов, таких как boost::vector и std::vector, требуется 1 аргумент шаблона (например, std::vector) Другим типам векторов, таким как etl::vector, может потребоваться больше аргументов шаблона. etl::vector, например, является предварительно выделенным вектором, поэтому нам нужен максимальный размер вектора (т.е. etl::vector<int, 100>)
Является ли Vector_T
параметром шаблона шаблона?
И что такое pop_into
? Вы имели в виду pop_back
?
IVector_T
имеет дополнительный параметр шаблона Element_T
. Это, вероятно, не то, что вы хотите. Требуйте, чтобы T::value_type
был типом, и используйте его вместо этого.
извини моя вина. Замените pop_into(). и да, Vector_T — это параметр шаблона шаблона. Типы Vector_T могут быть std::vector<T> и etl::vector<T, MAX_VEC_SIZE>.
@н.м. как я могу использовать T::value_type в этом контексте?
Смотрите это демо. Обратите внимание, что это работает совсем не так, как все предлагаемые решения. В этой демонстрации вы всегда работаете с std::vector<int>
, а не с двумя отдельными сущностями std::vector
и int
, или std::vector<int>
и int
, или чем-то еще. В демонстрации вектор даже не обязательно должен быть экземпляром шаблона. Или это может быть экземпляр шаблона с большим количеством параметров. Это тип, а не шаблон.
Я бы использовал более явный синтаксис. Это компилирует:
template<typename Element_T,
template <typename Elem> typename Vector_T>
requires IVector_T<Vector_T<Element_T>, Element_T>
class TestVector
{
...
(Однако я не пытался скомпилировать один из его экземпляров.)
Ваш Vector_T
— это шаблон, поэтому я думаю, что необходимо явно превратить TestVector
в «шаблон шаблона».
Кроме того, IVector_T
требует двух аргументов, поэтому использование template <IVector_T Vector_T>
некорректно: каким будет другой аргумент?
Не уверен, как вы планируете создавать экземпляр этого типа, но, учитывая переменную-член, я подозреваю, что вы неправильно указали аргументы шаблона:
template<typename Element_T, template <typename> typename Vector_T>
requires(IVector_T<Vector_T<Element_T>, Element_T>)
class TestVector { // ...
Вы должны создать экземпляр шаблона Vector_T
следующим образом.
template<typename Element_T, IVector_T<Element_T> Vector_T>
class TestVector
{
...
private:
Vector_T myVec;
};
Отвечает ли это на ваш вопрос? Можно ли использовать понятия с параметрами шаблона шаблона?