adjacent_difference结合back_inserter插入vector<vector<int>>编译失败求助
std::adjacent_difference配合返回vector<int>的diff函数插入vector<vector<int>>的问题 看起来你遇到的核心问题是:当std::adjacent_difference调用返回std::vector<int>的自定义diff函数时,std::back_inserter无法正确插入到std::vector<std::vector<int>>中,但返回int时却能正常工作。这其实是adjacent_difference的语义特性导致的类型不匹配问题,咱们一步步拆解解决:
为什么返回int时正常,返回vector<int>时编译失败?
std::adjacent_difference的默认行为是:
- 先将第一个输入元素直接复制到输出迭代器
- 再对每一对相邻元素(
input[i-1], input[i])调用自定义diff函数,将结果写入输出迭代器
当你的输出容器是vector<int>、diff返回int时:第一个输入元素是int,diff结果也是int,类型完全匹配,所以back_inserter能正常工作。
但当输出容器是vector<vector<int>>、diff返回vector<int>时:第一个要输出的元素是int(来自输入的第一个元素),但容器只能接受vector<int>类型,这就触发了编译时类型不匹配错误。
解决方案一:用std::transform处理相邻元素对(推荐)
如果你只需要相邻元素对的diff结果,不需要保留adjacent_difference自带的第一个元素输出,那么std::transform是更合适的选择——它可以直接遍历两对错开的输入迭代器,跳过第一个元素的类型问题:
#include <vector> #include <algorithm> #include <iterator> // 你的自定义diff函数 std::vector<int> dif(int prev, int curr) { // 示例:返回差值和和值的组合 return {curr - prev, curr + prev}; } int main() { std::vector<int> input = {1,2,3,4,5}; std::vector<std::vector<int>> output; if (!input.empty()) { // 用两个错开的迭代器遍历相邻元素对 std::transform( input.begin(), std::prev(input.end()), // 前一个元素的范围 std::next(input.begin()), // 当前元素的范围起始 std::back_inserter(output), // 输出插入器 dif // 自定义处理函数 ); } // 此时output中的元素是:{1,3}, {1,5}, {1,7}, {1,9} return 0; }
解决方案二:保留adjacent_difference语义(含第一个元素)
如果你需要保留adjacent_difference的完整语义(即输出第一个输入元素+后续相邻对的diff结果),可以通过两种方式处理类型不匹配:
方式1:手动处理第一个元素
先手动将第一个输入元素包装成vector<int>插入容器,再对剩余元素调用adjacent_difference:
#include <vector> #include <numeric> #include <iterator> std::vector<int> dif(int prev, int curr) { return {curr - prev, curr + prev}; } int main() { std::vector<int> input = {1,2,3,4,5}; std::vector<std::vector<int>> output; if (!input.empty()) { // 手动插入第一个元素的包装 output.push_back({input[0]}); // 对剩余元素调用adjacent_difference,输出从第二个位置开始 std::adjacent_difference( std::next(input.begin()), input.end(), std::next(output.begin()), dif ); } // 此时output中的元素是:{1}, {1,3}, {1,5}, {1,7}, {1,9} return 0; }
方式2:自定义适配输出迭代器
写一个可以同时接受int和vector<int>的插入迭代器,自动将int包装成vector<int>:
#include <vector> #include <numeric> #include <iterator> #include <utility> // 自定义插入迭代器,适配int到vector<int>的转换 struct VecBackInserter { std::vector<std::vector<int>>& target; explicit VecBackInserter(std::vector<std::vector<int>>& vec) : target(vec) {} // 处理int类型(第一个元素) VecBackInserter& operator=(int val) { target.push_back({val}); return *this; } // 处理vector<int>类型(diff结果) VecBackInserter& operator=(std::vector<int> val) { target.push_back(std::move(val)); return *this; } // 输出迭代器必需的类型定义和空操作 using value_type = void; using difference_type = void; using pointer = void; using reference = void; using iterator_category = std::output_iterator_tag; VecBackInserter& operator*() { return *this; } VecBackInserter& operator++() { return *this; } VecBackInserter operator++(int) { return *this; } }; std::vector<int> dif(int prev, int curr) { return {curr - prev, curr + prev}; } int main() { std::vector<int> input = {1,2,3,4,5}; std::vector<std::vector<int>> output; std::adjacent_difference( input.begin(), input.end(), VecBackInserter(output), dif ); // 此时output中的元素是:{1}, {1,3}, {1,5}, {1,7}, {1,9} return 0; }
内容的提问来源于stack exchange,提问作者Евгений Куркин

