STL const_iterator强制转换——编译器差异
STL const_iterator cast -- compiler differences
我正在将一大块代码从gcc移植到Visual Studio 2013。下面的代码示例在gcc 4.4上运行良好(!),但是在VS2013上编译begin()
和end()
失败:
错误C2440: ":无法从'unsigned char *'转换为'std::_Vector_const_iterator>>'
class foo {
unsigned char* value;
int length;
std::vector<unsigned char>::const_iterator begin();
std::vector<unsigned char>::const_iterator end();
};
std::vector<unsigned char>::const_iterator foo::begin() {
return std::vector<unsigned char>::const_iterator(value);
}
std::vector<unsigned char>::const_iterator foo::end() {
return std::vector<unsigned char>::const_iterator(value + length);
}
考虑到我不想重写整个东西,是否有一种可移植的方法来创建这些const_iterator ?
没有可移植的方法来做你正在尝试的事情,因为没有要求(const_)iterator
可以从指向底层值类型的指针构造。libstdc++碰巧提供了这样一个构造函数,但VS标准库实现没有。相反,它的(const_)iterator
构造函数接受一个指向底层值类型的指针和一个指向容器本身的指针,它使用它们在调试构建期间执行额外的验证。
最简单的解决方案是用unsigned char const *
代替std::vector<unsigned char>::const_iterator
。原始指针属于RandomAccessIterator类别,这与 vector::(const_)iterator
s相同。
unsigned char const *foo::begin() {
return value;
}
unsigned char const *foo::end() {
return value + length;
}
如果需要迭代器为类类型,则需要创建自定义迭代器。虽然这可以从头开始,但使用Boost要容易得多。IteratorFacade,它将提供一堆必要的样板,用于构造自定义迭代器。
#include <boost/iterator/iterator_facade.hpp>
struct const_foo_iterator : boost::iterator_facade<const_foo_iterator,
unsigned char const,
boost::random_access_traversal_tag>
{
const_foo_iterator() = default;
const_foo_iterator(unsigned char const *iter) : iter(iter) {}
private:
friend class boost::iterator_core_access;
void increment() { ++iter; }
void decrement() { --iter; }
void advance(std::ptrdiff_t n) { iter += n; }
std::ptrdiff_t distance_to(const_foo_iterator const& other) const
{ return iter - other.iter; }
bool equal(const_foo_iterator const& other) const
{ return this->iter == other.iter; }
unsigned char const& dereference() const { return *iter; }
unsigned char const* iter = nullptr;
};
const_foo_iterator foo::begin() {
return value;
}
const_foo_iterator foo::end() {
return value + length;
}
static_assert(std::is_same<std::iterator_traits<const_foo_iterator>::value_type,
unsigned char>::value, "value_type");
static_assert(std::is_same<std::iterator_traits<const_foo_iterator>::pointer,
unsigned char const *>::value, "pointer");
static_assert(std::is_same<std::iterator_traits<const_foo_iterator>::iterator_category,
std::random_access_iterator_tag>::value, "iterator_category");
现场演示
这取决于如何使用begin()
和end()
函数。如果这些函数的调用者实际上期望std::vector<unsigned char>::const_iterator
(而不是足够通用而不关心确切类型),那么您必须搜索不同的解决方案。
与其更改类的接口,不如尝试在其实现中实现一个变通方法。value
指针需要做什么?还有谁有权限?如果它是私有成员,那么只需将其替换为实际的std::vector<unsigned char>
,并使用其data()
成员函数(c++ 11)或&value[0]
(c++ 11之前)来传递期望的指针。
- 奇怪的缩小转换在 g++ 编译器中加倍到浮点警告
- 在不同的编译器上转换为 void**
- 为什么我的编译器无法弄清楚这种转换,它何时存在?
- 为什么编译器抱怨 std::thread 参数在转换为右值后必须是可调用的?
- 为什么我的编译器在调用 const getter 函数时抛出"转换丢失(const)限定符"错误?
- 从 int 中剥离位时,编译器会警告一个转换,但不警告其他转换.有解决方法吗?
- AIX编译器13.1.3对c++进行了不正确的双重转换
- 我把我的编译器从32位转换为64位,但我仍然不能使用超过2GB:(为什么
- 是否允许此编译器转换?
- 对从引用到 std::reference_wrapper 或编译器错误的隐式转换的理解不正确?
- std::chrono::time_point 从变量转换时编译器错误
- 将编译器命令行转换为 CMakeLists.txt用于 Casablanca Rest SDK
- C++函数到指针的隐式转换:哪个编译器是正确的?Clang和GCC不同意
- Arm GNU编译器:通过多余的强制转换优化的三进制生成的程序集
- Windows VC++编译器允许一种奇怪的c样式转换方式(或者它可能不是转换??)
- GCC 编译器对类型转换有什么作用?为什么 mac 和 Linux 上的输出不同
- 为什么C 标准要求编译器忽略对基本类型转换操作员的呼叫
- 现代编译器优化如何将递归转换为返回常数
- 编译器可以静默地从 const 转换为 const 和,反之亦然吗?
- 为什么 xlc++ 编译器抱怨强制转换右值