I have a big serialization library that rely on boost::has_range_const_iterator
. The below code is part of a serialization library used in a game network.
template<typename T>
auto operator()(T const& vals) const -> typename std::enable_if<boost::has_range_const_iterator<T>::value>::type
{
auto length = std::distance(std::begin(vals), std::end(vals));
if (length > std::numeric_limits<uint16_t>::max())
throw BadMessage("Length is too big to fit into length variable");
(*this)(static_cast<uint16_t>(length));
for (auto& val : vals)
(*this)(val);
}
Is there some replacement in std
for boost::has_range_const_iterator
in the above context?
EDIT: What i have tried?
#include <iterator>
#include <list>
#include <vector>
#include <type_traits>
#include <iostream>
template <typename T>
struct has_const_iterator {
private:
template <typename C>
static std::true_type test(typename std::add_const<typename C::const_iterator>::type*);
template <typename C>
static std::false_type test(...);
public:
static const bool value = decltype(test<T>(nullptr))::value;
};
int main() {
// Example usage:
std::vector<int> vec;
if ( has_const_iterator<decltype(vec)>::value )
std::cout << "Vector has a const iterator.";
std::list<int> myList;
if (!has_const_iterator<decltype(myList)>::value)
std::cout << "List does not have a const iterator.";
return 0;
}
it is good like this? Has anyone a better alternative ?
You could probably use the concept
std::ranges::input_range
instead:
#include <ranges>
auto operator()(std::ranges::input_range auto&& vals) const {
auto length = std::distance(std::ranges::cbegin(vals),
std::ranges::cend(vals));
//...
}
You could also create a concept
of your own to explicitly check if std::ranges::cbegin
and cend
are supported (although the standard range
concept is most probably enough):
template <class T>
concept const_iterable = requires(T& t) {
std::ranges::cbegin(t);
std::ranges::cend(t);
};
You could also simplify your type trait somewhat:
template <class, class = void>
struct has_const_iterator : std::false_type {};
template <class T>
struct has_const_iterator<
T, std::void_t<decltype(std::begin(std::declval<const T&>()))>>
: std::true_type {};
// helper variable:
template <class T>
inline constexpr bool has_const_iterator_v = has_const_iterator<T>::value;