Let's say a class is a MyContainer<T>
if it has
size_t size()
T& operator[](size_t index)
const T& operator[](size_t index)
and I want to write a template function that accept a specific version of MyContainer, for example any container that indexes int values and float values
float add(const MyContainer<int> &left, const MyContainer<float> &right);
and use it like
vector<int> a;
some_custom_vector<float> b;
float res = add(a, b);
How can I achieve that?
I cannot use auto
because I want to specify inner type
// can not specify inner type
template<typename MyContainer>
float add(const MyContainer &left, const MyContainer &right);
// can not specify inner type either
auto add(const auto &left, const auto &right);
I also tried using template <template <class> class MyContainer>
, but the compiler can't infer the inner template parameter.
You want a concept
:
#include <cstddef>
#include <concepts>
template <typename C, typename T>
concept MyContainer = requires(C &c, const C &cc, std::size_t n)
{
{ cc.size() } -> std::same_as<std::size_t>;
{ c[n] } -> std::same_as<T &>;
{ cc[n] } -> std::same_as<const T &>;
};
float add(const MyContainer<int> auto &left, const MyContainer<float> auto &right) {}
Note that, rather than specifying the custom container requirements like this, it's better to rely on built-in concepts from <ranges>
:
template <typename C, typename T>
concept MyContainer = std::ranges::random_access_range<C>
&& std::same_as<std::ranges::range_value_t<C>, T>;
float add(MyContainer<int> auto &&left, MyContainer<float> auto &&right)