我正在编写一些代码,它从具有任何泛型类型的给定 vector 中随机选择一个元素。我已经成功地创建了一个返回随机元素拷贝的函数,但是如果有一个类似的函数可以返回该元素的迭代器,那对我来说会很方便。这就是我所拥有的,其中随机迭代器是通过生成器函数向开始迭代器添加随机数产生的:
template <class T>
typename std::vector<T>::iterator pickElementIterator(const std::vector<T>& v)
{
if (v.empty())
{
// error
return v.end();
}
return v.begin() + generate(v.size());
}
如果没有代码使用它,则编译成功。但是,一旦我尝试用 Foo 类型替换某个 vector ,使用 g++ 就会出现以下错误:could not convert '(& v)->std::vector::end()' from '__normal_iterator<const Foo*,[...]>' to
__normal_iterator<Foo*,[...]>'
对于两个返回。似乎在尝试将其转换为返回时,它向类型添加了一个 const。我在两个返回上都尝试了 std::decay ,但它不接受这些参数。就我对模板编程的了解而言,这就是我所看到的任何地方都没有太多关于这方面的知识。
注: “typename”在返回类型中,否则 g++ 会提示:
need 'typename' before 'std::vector<_RealType>::iterator' because 'std::vector<_RealType>' is a dependent scope Which is still not clear for me.
最佳答案
std::vector<T>::begin()
/std::vector<T>::end()
返回 const_iterator
当const
合格,不是 iterator
(这是可变的)。
编译失败的原因是const_iterator
s 无法转换为可变 iterator
类型。修复很简单:将返回类型更改为 const_iterator
:
template <class T>
typename std::vector<T>::const_iterator pickElementIterator(const std::vector<T>& v)
// ^~~~~~~~~~~~~~
如果您在 c++14或以上,您也可以使用 auto
没有声明的返回类型,以便它可以自行推断,例如:template <class T>
auto pickElementIterator(const std::vector<T>& v)
注:您观察到在不使用时编译成功的原因是因为模板在实例化之前无法完全评估。由于模板特化,编译器必须假设任何依赖模板参数(例如,类型
T
)的东西都可能产生有效的实例化。例如,编译器必须假定可能存在
T
这样const std::vector<T>::begin()
返回可以构造 std::vector<T>::iterator
的东西.如果 vector<T>
可能会发生这种情况是专门的。因此,在实际实例化模板之前,您不会经常看到语法错误之外的许多诊断
关于c++ - 从模板化 vector 函数中删除 cv-qualifier,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65029161/