c++ - 从模板化 vector 函数中删除 cv-qualifier

标签 c++ g++

我正在编写一些代码,它从具有任何泛型类型的给定 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_iteratorconst合格,不是 iterator (这是可变的)。
编译失败的原因是const_iterator s 无法转换为可变 iterator类型。修复很简单:将返回类型更改为 const_iterator :

template <class T>
typename std::vector<T>::const_iterator pickElementIterator(const std::vector<T>& v)
//                       ^~~~~~~~~~~~~~
如果您在 或以上,您也可以使用 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/

相关文章:

c++ - sizeof struct gcc 编译成功,但 g++ 编译失败

c++ - 使用 Visual Studio 2008 编译但不使用 g++ 的引用相关问题

c++ - 获得两倍宽的字体

c++ - 在openmesh中计算三角形的面积

c++ - 模板元编程 :why flat type is failure

c++ - 为什么不同 block 中相同命名的外部局部变量在 C++ 中的编译器之间获得不同的链接?

c++ - 创建包含字符串和 std::endl 的变量,可用于 std::cout 的输出流

c++ - 在 C++ 中正确使用 assert()

c++ - g++模板参数错误

c++ - 为什么g++在动态链接时会检测到 undefined reference