我尝试在商业应用程序中使用 View ,并注意到 gcc 和 Visual Studio 之间的不一致。
在下面的代码中,调用 transformed()
两次返回两个不同的、显然不兼容的 View 。在 gcc 11(在 godbolt 上)中,即使进行了额外的调试,代码执行也没有问题,但在 Visual Studio 16.11 中 -std:c++latest
,它断言:
cannot compare incompatible transform_view iterators
我希望我的函数可以被调用,就像它返回 const std::vector<std::pair<int, int>> &
一样。所以调用者不必担心临时变量。看来我可以使我的转换 View 成为我的类的成员,在构造函数中初始化它,然后返回它,但我什至不知道如何声明它。
我假设 Visual Studio 是正确的,而我的代码是非法的,但即使我的代码应该合法,它仍然必须工作。我们拥有 10,000,000 行代码库和许多非专业 C++ 程序员,我需要核心足够强大,并且没有像这样的隐藏陷阱。
#include <iostream>
#include <ranges>
#include <vector>
struct X
{
std::vector<int> m_values{ 1,2,3 };
auto transformed() const
{
return std::ranges::views::transform(m_values, [](int i) {
return std::pair{ i, i + i };
});
}
};
int main()
{
X x;
for (auto [a, b] : x.transformed())
std::cout << a << " " << b << std::endl;
if (x.transformed().begin() != x.transformed().end()) // asserts in visual studio.
std::cout << "not empty";
return 0;
}
最佳答案
It seems that I could make my transformed view a member of my class, initialize it in the constructor, and return that, but I don't even know how to declare it.
您可以将X
转换为模板类,并通过传递的lambda构造成员transform_view
,如下所示:
#include <iostream>
#include <ranges>
#include <vector>
template<class F>
struct X {
std::vector<int> m_values{1,2,3};
decltype(m_values | std::views::transform(std::declval<F>())) m_transformed;
X(F fun) : m_transformed(m_values | std::views::transform(std::move(fun))) { }
const auto& transformed() const { return m_transformed; }
};
int main() {
X x([](int i) { return std::pair{i, i + i}; });
for (auto [a, b] : x.transformed())
std::cout << a << " " << b << std::endl;
if (x.transformed().begin() != x.transformed().end())
std::cout << "not empty";
}
另一种方法是使用 std::function
,这使得您的 X
不必是模板类:
struct X {
using Fun = std::function<std::pair<int, int>(int)>;
std::vector<int> m_values{1,2,3};
decltype(m_values | std::views::transform(Fun{})) m_transformed;
X(Fun fun = [](int i) { return std::pair{i, i + i}; })
: m_transformed(m_values | std::views::transform(std::move(fun))) { }
const auto& transformed() const { return m_transformed; }
};
关于c++ - 使用相同 std::view 的两个不同拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70039388/