C++ const correction编译错误到模板函数中的无效转换错误

C++ const correction编译错误到模板函数中的无效转换错误,c++,c++11,templates,C++,C++11,Templates,我构建了一个函数,该函数可以将单个偏移量编号偏移量取消绑定到索引数组rindex。我用它来获得高维网格的相应索引。诚然,该函数的反向迭代器看起来有点古怪,但它可以工作,我现在不知道如何做得不同 现在,一旦我对边界变量const进行了限定,我就会得到一个关于反向迭代器的非常神秘的编译时错误。谁能帮我一点忙吗 #include <array> #include <iostream> template <typename size_type, typename crIt,

我构建了一个函数,该函数可以将单个偏移量编号偏移量取消绑定到索引数组rindex。我用它来获得高维网格的相应索引。诚然,该函数的反向迭代器看起来有点古怪,但它可以工作,我现在不知道如何做得不同

现在,一旦我对边界变量const进行了限定,我就会得到一个关于反向迭代器的非常神秘的编译时错误。谁能帮我一点忙吗

#include <array>
#include <iostream>
template <typename size_type, typename crIt, typename rIt>
constexpr size_type unpeel(size_type offset, const crIt rbegin, const crIt rend,
                           rIt rindex) {
  for (rIt rit = rbegin; rit != rend; rit++) {
    *rindex++ = offset % *rit;
    offset /= *rit;
  }
  return offset;
}

int main() {
  size_t count = 0;
  constexpr size_t N = 2;
  const std::array<size_t, N> bounds{{2, 3}};
  std::array<size_t, N> index{};
  unpeel(0, bounds.rbegin(), bounds.rend(), index.rbegin());
}

#include

迭代器
rbegin
不可分配给
rit
-您需要将其声明为常量迭代器(或者干脆称为
auto
):

因为您是通过值传递的,所以您可以

while (rbegin != rend) {
  *rindex++ = offset % *rbegin;
   offset /= *rbegin++;
}

完整,已成功编译,代码:

template <typename size_type, typename InputIterator, typename OutputIterator>
constexpr size_type unpeel(size_type offset,
                           InputIterator rbegin,
                           InputIterator rend,
                           OutputIterator rindex)
{
    for (; rbegin != rend;  ++rbegin) {
        *rindex++ = offset % *rbegin;
        offset /= *rbegin;
    }
    return offset;
}

#include <array>
#include <iostream>
int main() {
    constexpr size_t N = 2;
    const std::array<size_t, N> bounds{{2, 3}};
    std::array<size_t, N> index{};
    unpeel(0, bounds.rbegin(), bounds.rend(), index.rbegin());
}
模板
constexpr尺寸类型取消捆扎(尺寸类型偏移,
输入计数器rbegin,
输入迭代器格式,
输出计数器(rindex)
{
对于(;rbegin!=rend;++rbegin){
*rindex++=偏移量%*rbegin;
偏移/=*rbegin;
}
返回偏移量;
}
#包括
#包括
int main(){
constexpr size\u t N=2;
常量std::数组边界{{2,3};
std::数组索引{};
取消显示(0,bounds.rbegin(),bounds.rend(),index.rbegin());
}

我对迭代器模板类型使用了传统的类型名称,以使需求更清晰。

这是编译器错误还是异常?“Throws”似乎意味着运行时异常,但“const correction”通常会导致编译时错误。“rit”是一个非常量反向迭代器(从它可以修改指向的对象的意义上讲),“rbegin”是一个常量反向迭代器(从它不能修改指向的对象的意义上讲)。在for循环行6的初始化过程中,使用常量反向迭代器初始化非常量反向迭代器。试着把“for(rIt…”变成“for(crIt…)()?@JonasK Dammit,我知道“constant”在这里会有误导性。事实上,我这里说的不是关键字“const”,而是“iterator”和“const_iterator”,这是两种不同的类型,特别是const_iterator从来都不是“const iterator”.Container类提供这两种类型,它们都可以递增或以其他方式进行变异,但常量迭代器不允许您变异它所指向的对象。基本上,如果您的迭代器类型是int*,则常量迭代器类型将是const int*(理解)(const int)*),而“const迭代器”将是int*const(理解“const(int*))事实上,rbegin甚至是一个常量(关键字const,即不允许修改rbegin)常量迭代器(即不允许修改*rbegin)。与rend相同。函数签名中的const关键字实际上没有帮助,因为您已经按值获取了内容,但它们也不一定有害。如果您从代码中删除它们,则应该会出现完全相同的错误。它实际上源于“crbegin()中的小“c”您在编辑之前使用的,这意味着“使用常量版本的迭代器”您试图从常量指针获取非常量指针,这可能会导致违反常量正确性。请将
rit
声明为
crIt rit=rbegin
template <typename size_type, typename InputIterator, typename OutputIterator>
constexpr size_type unpeel(size_type offset,
                           InputIterator rbegin,
                           InputIterator rend,
                           OutputIterator rindex)
{
    for (; rbegin != rend;  ++rbegin) {
        *rindex++ = offset % *rbegin;
        offset /= *rbegin;
    }
    return offset;
}

#include <array>
#include <iostream>
int main() {
    constexpr size_t N = 2;
    const std::array<size_t, N> bounds{{2, 3}};
    std::array<size_t, N> index{};
    unpeel(0, bounds.rbegin(), bounds.rend(), index.rbegin());
}