EDIT 3:
I will leave my old posts for anyone who is interested. However, I just found the obvious solution...
#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>
With this approach you can just use span everywhere and program as usual.
ORIGINAL:
One solution would be to use a template for the span with a default value. Like:
template <template<class,size_t> class Span>
void read_data(Span<float> data);
However, you can run into problems with the various libraries using different signature for their containers. Thus, the better way would be to do:
template <class Span>
void read_data(Span data);
You are missing the type of the values now, but you should be able to retrieve it with:
using T = typename Span::value_type
In addition, you might want to add some std::enable_if
(or Concepts) to your functions, which checks if Span
actually provides the member functions you are using.
In practice, all of the above can result in very noisy code. If you only have a simple case, the easier way might be to define span with a using
declaration of the library user.
The above will probably not work well with the std::vector
overloads because the type signatures are somewhat similar. You can solve this by providing explicit std::vector
overloads which do the right casts and call the Span
version.
EDIT:
From your comment I gather that you want to convert a unspecified type (any container) to a unspecified type (any span). This neither makes sense nor is possible. You will need to define one of the types somewhere.
That being said, you could write conversion independent code and let the user provide the actual conversion. Like:
template <class Span>
void read_data_impl(Span data);
template <class Container>
void read_data(Container data)
{
read_data_impl(convert(data));
}
The user would then need to supply:
template <class Container>
auto convert(Container& data)
{
return USERSPAN(data);
}
EDIT 2:
There was a bug in my code. The data
in the convert function has to be passed by reference. In addition, it is probably helpful if you pass allow passing a T
for the container value by hand. Thus you end up with:
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));
}
And for conversion:
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);
}
The user then has to supply the following function:
template <class T, class Container>
auto convert_impl(Container& data)
{
return USERSPAN<T>(data);
}