Boost::has_range_const_iterator 替换为 STD

boost::has_range_const_iterator replacement with std

提问人:xapi 提问时间:10/31/2023 最后编辑:xapi 更新时间:10/31/2023 访问量:57

问:

我有一个大型序列化库,依赖于 .以下代码是游戏网络中使用的序列化库的一部分。boost::has_range_const_iterator

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);
}

在上述情况下,是否有一些替代品?stdboost::has_range_const_iterator

编辑: 我试过什么?

#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;
}

这样好吗?有没有人更好的选择?

C++ 序列化 std boost-range

评论


答:

1赞 Ted Lyngmo 10/31/2023 #1

你可以改用 std::ranges::input_rangeconcept

#include <ranges>

auto operator()(std::ranges::input_range auto&& vals) const {
    auto length = std::distance(std::ranges::cbegin(vals),
                                std::ranges::cend(vals));

    //...
}

您也可以创建一个自己的 和 来明确检查是否支持 和 是否受支持(尽管标准范围概念很可能就足够了):conceptstd::ranges::cbegincend

template <class T>
concept const_iterable = requires(T& t) {
    std::ranges::cbegin(t);
    std::ranges::cend(t);
};

你也可以稍微简化你的类型特征:

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;

评论

0赞 xapi 10/31/2023
请检查我的编辑,看看你是否可以改进我编辑的内容等等。
0赞 Ted Lyngmo 10/31/2023
@xapi我添加了一些替代方案。但是,您从标准库中请求了某些内容,在这种情况下,(或)很可能最接近您的要求。你有没有尝试过像我展示的那样使用?std::ranges::input_rangestd::ranges::rangeinput_range