c++ - 为什么 Clang 不喜欢 boost::transform_iterator?
问题描述
使用 Clang 8.0.1 和 Boost 1.70,以下程序
// transform.cpp
#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/iterator/transform_iterator.hpp>
struct Foo
{
int x;
};
struct XGetter
{
auto operator()(const Foo& foo) const noexcept { return foo.x; }
};
int main()
{
const std::vector<Foo> foos {{1}, {2}, {3}};
using boost::make_transform_iterator;
const auto first = make_transform_iterator(foos.cbegin(), XGetter {});
const auto last = make_transform_iterator(foos.cend(), XGetter {});
std::cout << *std::max_element(first, last) << std::endl;
}
编译失败
$ clang++ -std=c++14 -o transform transform.cpp
/usr/local/Cellar/llvm/8.0.1/bin/../include/c++/v1/algorithm:2494:5: error: static_assert failed due to requirement
'__is_forward_iterator<boost::iterators::transform_iterator<XGetter, std::__1::__wrap_iter<const Foo *>,
boost::use_default, boost::use_default> >::value' "std::max_element requires a ForwardIterator"
static_assert(__is_forward_iterator<_ForwardIterator>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/Cellar/llvm/8.0.1/bin/../include/c++/v1/algorithm:2512:19: note: in instantiation of function template
specialization 'std::__1::max_element<boost::iterators::transform_iterator<XGetter, std::__1::__wrap_iter<const
Foo *>, boost::use_default, boost::use_default>, std::__1::__less<int, int> >' requested here
return _VSTD::max_element(__first, __last,
^
transform.cpp:24:24: note: in instantiation of function template specialization
'std::__1::max_element<boost::iterators::transform_iterator<XGetter, std::__1::__wrap_iter<const Foo *>,
boost::use_default, boost::use_default> >' requested here
std::cout << *std::max_element(first, last) << std::endl;
^
1 error generated.
我的印象是boost::transform_iterator继承了 it 模型的迭代器的迭代器类别。出了什么问题?
解决方案
(C++20 之前的)标准需要前向或更强的迭代器:
- 在取消引用时产生一个真实的引用;
- 当两个相等的迭代器被取消引用时产生对同一个对象的引用(即,没有存储)
由于您的转换按价值返回,因此无法transform_iterator
同时满足这两个要求。因此,它只能将自己宣传为输入迭代器。
解决方法是更改XGetter
为通过引用返回,或使用std::mem_fn(&Foo::x)
which 为您执行此操作。
推荐阅读
- android - Jackson 未能反序列化 Kotlin 类
- mongodb - Mongodb:使用字段作为对象数组进行查找
- javascript - 如何使用 puppeteer 下载当前页面的 pdf
- c# - 如何在 Blazor 服务器端应用程序中从本地 Active Directory 实施身份验证?
- c# - 自动完成(字符串和整数)的一个时髦的东西
- c++ - Pytorch C++ RuntimeError:设备类型为 cuda 的预期对象,但在调用 _th_index_select 时获得了参数 #1 'self' 的设备类型 cpu
- django - 在 Django 模型中进行迁移时出现“外键不匹配”错误
- reactjs - 如果所有记录都已处理,则仅重新加载页面
- azure - 如何使用 python 在 azure blob 存储中为 upload_blob 设置内容类型?
- typescript - 如何使用 typescript-fetch 使用 openapi-generator 生成真正简约的模型接口?