用于 STL 迭代器、指针和 std::nullptr_t 的模板函数
Template function for STL iterators, pointers and std::nullptr_t
我正在尝试围绕基于 c 的 API 函数编写一个包装器。
用户应该能够将 RandomAccessIterator、指针或 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
。
相关文章:
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 检查模板中 nullptr 的函数指针,了解任何类型的可调用对象
- CURLOPT_INTERLEAVEFUNCTION回调函数始终接收 nullptr 作为用户数据指针
- 函数 AfxEndThread 中的读取访问冲突"pThread-> was nullptr"
- 为什么分配了 nullptr 的指针可以调用成员函数?
- c++:成员函数中的"this == nullptr"安全吗?
- 为什么使用 nullPtr 调用函数不会使我的应用程序崩溃
- 返回其参数或检查 nullptr 的函数
- 我可以解决unique_ptr在<MyType>仅存储 nullptr 时不需要 MyType 析构函数定义吗?
- std::unique_ptr 是否在其析构函数中将其基础指针设置为 nullptr?
- 默认模板函数参数中的 boost::shared_ptr 和 nullptr
- 当调用析构函数时,是否可以将指向类实例的指针设置为nullptr
- 为什么函数模板不理解 NULL,但适用于 nullptr
- 具有显式定义的默认构造函数的 unique_ptr 到 nullptr 错误的类内成员初始值设定项
- std::将成员函数绑定到 nullptr 处的实例,导致看似随机的 this 指针
- C++ 通过多个函数传递 nullPTR
- 将 nullptr 分配给函数指针变量是否安全
- 检查std::函数是否已分配给nullptr
- Qt/GCC:按值从函数返回对象/nullptr.为什么要编译此代码