gpt4 book ai didi

c++ - 使用 declval 获取非常量迭代器

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:59:22 27 4
gpt4 key购买 nike

一个最小的例子,展示了两种获取迭代器类型的方法,我天真地希望得到与结果相同的类型:

template <typename Range>
struct foo
{
using iterator = decltype(std::begin(std::declval<Range>()));
using iterator2 = typename Range::iterator;

static_assert(std::is_same<iterator, iterator2>::value, "Iterator types differ!");
};

int main()
{
std::vector<int> v;
foo<decltype(v)> f;
}

但这实际上触发了静态断言。

如果我们将第一个迭代器更改为:

using iterator = decltype(std::declval<Range>().begin());

没有触发静态断言。

查看 std::begin() 的定义,它对引用和常量引用类型都进行了重载。由于 declval 返回一个右值引用,这只会绑定(bind)到一个 const 引用,从而返回一个 const 迭代器类型。

这可以通过使用引用折叠来解决,这有点令人厌恶:

using iterator = decltype(std::begin(std::declval<typename std::add_lvalue_reference<Range>::type>()));

有没有更简单的方法来获取非常量迭代器?显然 typename Range::iterator 不会对所有类型都存在(例如 T*),同样对于成员 begin() , 因此两者都不是理想的。

最佳答案

直接调用 std::begin 甚至不是获取开始迭代器的正确方法。正确的习语需要两个语句: using std::begin;开始(rng);。这显然不能在 decltype 中完成。

你这样做的方式不适用于没有成员 begin/endstd::begin/的类型结束重载。

因此正确的解决方案是创建一个执行此操作的函数:

template<typename Range>
auto my_begin(Range &&rng)
{
using std::begin;
return begin(std::forward<Range>(rng));
}

然后在您的 decltype 字段中调用该函数。

关于c++ - 使用 declval 获取非常量迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50905808/

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