gpt4 book ai didi

c++ - STL 迭代器、指针和 std::nullptr_t 的模板函数

转载 作者:行者123 更新时间:2023-11-30 04:43:27 26 4
gpt4 key购买 nike

我正在尝试围绕基于 C 的 API 函数编写一个包装器。
用户应该能够将 RandomAccessIterators、指针或 nullptr 作为参数传递给包装函数。

#include <type_traits>
#include <iterator>

template <typename Iter>
constexpr bool is_random_access_iterator_v = std::is_convertible_v<typename std::iterator_traits<Iter>::iterator_category, std::random_access_iterator_tag>;

template <typename Iter>
using iterater_decayed_type_t = std::decay_t<typename std::iterator_traits<Iter>::value_type>;

// convert iterator to pointer
template <typename Iter>
auto get_pointer(Iter it) {
if constexpr (std::is_null_pointer_v<Iter> || std::is_pointer_v<Iter>) {
return it;
} else {
return &*it;
}
}

// InputIter and OutputIter can be arbitrary iterator or pointer.
// OutputIter can also be a nullptr
template <typename InputIter, typename OutputIter>
OutputIter wrapper(InputIter first, InputIter last, OutputIter d_first) {
static_assert(is_random_access_iterator_v<InputIter>, "InputIter needs to be a RandomAccessIterator");
static_assert(std::is_null_pointer_v<OutputIter> || is_random_access_iterator_v<OutputIter>, "OutputIter needs to be a RandomAccessIterator or nullptr");
static_assert(std::is_null_pointer_v<OutputIter> || std::is_same_v<iterater_decayed_type_t<InputIter>, iterater_decayed_type_t<OutputIter>>, "Iterator value types must be identical or OutputIter is nullptr");

using value_t = iterater_decayed_type_t<InputIter>;

using first_ptr_t = typename std::iterator_traits<InputIter>::pointer;
first_ptr_t ptr_first = get_pointer(first);

using d_first_ptr_t = std::conditional_t<std::is_null_pointer_v<OutputIter>, std::nullptr_t, typename std::iterator_traits<OutputIter>::pointer>;
d_first_ptr_t ptr_d_first = get_pointer(d_first);

// func gets arbitrary pointers (void*)
func(ptr_first, ptr_d_first, last - first);
return d_first;
}

此代码无法编译,因为 std::iterator_traits<T>不专门用于 std::nullptr_t .

我已经想到了两种可能的解决方案:

1.) 专业std::iterator_traits<std::nullptr_t> ,例如:

namespace std {
template <>
struct iterator_traits<std::nullptr_t> {
using difference_type = std::ptrdiff_t;
using value_type = std::nullptr_t;
using pointer = std::nullptr_t;
using reference = std::nullptr_t;
using iterator_category = std::random_access_iterator_tag;
using iterator_concept = std::random_access_iterator_tag;
};
}

但据我所知,专门化 STL 命名空间成员会很快导致未定义的行为。

2.) 将功能拆分为两个函数。这里的问题是它会导致不必要的复制粘贴代码。此外,我想向原始函数添加几个重载,这将导致最后的函数数量增加两倍(例如,对于 4 个正常重载,我需要使用这种方法进行 8 个重载)。

所以我的问题是:
有什么方法可以引入可能的未定义行为并且必须创建两倍数量的重载函数来解决这个问题吗?
例如调整 is_random_access_iterator_v不依赖的特质std::iterator_traits

最佳答案

你不能专攻std::iterator_traits<std::nullptr_t> ,但您可以创建自己的特征:

template <typename T>
struct my_iterator_traits : iterator_traits<T> {};

template <>
struct my_iterator_traits<std::nullptr_t>
{
using difference_type = std::ptrdiff_t;
using value_type = std::nullptr_t;
using pointer = std::nullptr_t;
using reference = std::nullptr_t;
using iterator_category = std::random_access_iterator_tag;
using iterator_concept = std::random_access_iterator_tag;
};

并使用my_iterator_traits满足您的需求。

关于c++ - STL 迭代器、指针和 std::nullptr_t 的模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58276221/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com