РЕДАКТИРОВАТЬ 3:
Я оставлю свои старые сообщения для всех, кто заинтересован.Однако я только что нашел очевидное решение ...
#include <user_span>
//dive into your namespace to avoid name collisions
namespace YOUR_LIB
{
//supply custom type
template <class T, SIZET size = DEFAULT>
using span = ::user_span<T, size>;
}
//actually include the library
#include <your_lib>
При таком подходе вы можете просто использовать span везде и программировать как обычно.
ORIGINAL:
Одним из решений было бы использование шаблона для диапазона со значением по умолчанию.Например:
template <template<class,size_t> class Span>
void read_data(Span<float> data);
Однако вы можете столкнуться с проблемами с различными библиотеками, использующими разные сигнатуры для своих контейнеров.Таким образом, лучшим способом было бы сделать:
template <class Span>
void read_data(Span data);
Вам не хватает типа значений сейчас, но вы должны иметь возможность получить его с помощью:
using T = typename Span::value_type
Кроме тогоВы можете захотеть добавить некоторые std::enable_if
(или Концепции) к своим функциям, что проверяет, действительно ли Span
предоставляет функции-члены, которые вы используете.
На практике все вышеперечисленное может привести к оченьшумный код.Если у вас есть только простой случай, более простым способом может быть определение span с объявлением using
пользователя библиотеки.
Выше, вероятно, не будет хорошо работать с перегрузками std::vector
, потому что сигнатуры типовнесколько похожи.Вы можете решить эту проблему, предоставив явные перегрузки std::vector
, которые выполняют правильное приведение и вызывают версию Span
.
EDIT:
Из вашего комментария я понимаю, чтоВы хотите преобразовать неопределенный тип (любой контейнер) в неопределенный тип (любой диапазон).Это не имеет смысла и не возможно.Вам нужно будет где-то определить один из типов.
При этом вы можете написать независимый от преобразования код и позволить пользователю обеспечить фактическое преобразование.Например:
template <class Span>
void read_data_impl(Span data);
template <class Container>
void read_data(Container data)
{
read_data_impl(convert(data));
}
Пользователь должен будет указать:
template <class Container>
auto convert(Container& data)
{
return USERSPAN(data);
}
РЕДАКТИРОВАТЬ 2:
В моем коде произошла ошибка,data
в функции преобразования должен быть передан по ссылке.Кроме того, вероятно, будет полезно, если вы передадите allow, передавая T
для значения контейнера вручную.Таким образом, вы получите:
template <class Span>
void read_data_impl(Span data);
template <class Container>
void read_data(Container data)
{
read_data_impl(convert(data));
}
template <class T, class Container>
void read_data(Container data)
{
read_data_impl(convert<T>(data));
}
И для преобразования:
template <class T, class Container>
auto convert(Container& data)
{
return convert_impl<T>(data);
}
template <class Container>
auto convert(Container& data)
{
return convert_impl<typename Container::value_type>(data);
}
Затем пользователь должен предоставить следующую функцию:
template <class T, class Container>
auto convert_impl(Container& data)
{
return USERSPAN<T>(data);
}