首页 > 解决方案 > 如何将一个类型专门化为一个范围?

问题描述

我一直在尝试使自定义类型符合范围的要求。在 c++ 标准中,范围定义如下:

template< class T >
concept range = requires(T& t) {
  ranges::begin(t); // equality-preserving for forward iterators
  ranges::end  (t);
};

因此,正如您在我的示例中所看到的,我已经覆盖了所需的功能。但是,它不能为我编译,因为它找不到迭代器的 const 版本:

prog.cc: In instantiation of 'void some_algorithm(const range&) [with range = Foo]':
prog.cc:42:21:   required from here
prog.cc:29:3: error: passing 'const Foo' as 'this' argument discards qualifiers [-fpermissive]
   29 |   for (const auto& x : r)
      |   ^~~
prog.cc:11:8: note:   in call to 'auto Foo::begin()'
   11 |   auto begin() { return vec.begin(); }
      |        ^~~~~
prog.cc:29:3: error: passing 'const Foo' as 'this' argument discards qualifiers [-fpermissive]
   29 |   for (const auto& x : r)
      |   ^~~
prog.cc:12:8: note:   in call to 'auto Foo::end()'
   12 |   auto end() { return vec.end(); }

这是我使用的代码:

// This file is a "Hello, world!" in C++ language by GCC for wandbox.
#include <iostream>
#include <cstdlib>
#include <ranges>
#include <vector>

struct Foo
{
  std::vector<int> vec;
  
  auto begin() { return vec.begin(); }
  auto end() { return vec.end(); }
  auto cbegin() const { return vec.cbegin(); }
  auto cend() const { return vec.cend(); }
  auto size() const { return vec.size(); }
};

namespace std::ranges
{
  auto begin(Foo& x) { return x.begin(); }
  auto end(Foo& x) { return x.end(); }
  auto cbegin(const Foo& x) { return x.cbegin(); }
  auto cend(const Foo& x) { return x.cend(); }
}

template <std::ranges::range range>
void some_algorithm(const range& r)
{
  for (const auto& x : r)
  {
    std::cout << x << '\n';
  }
}

int main()
{
    auto f = Foo { { 1, 2, 3, 4 } };
    
    some_algorithm(f.vec); // this works!
    //some_algorithm(f); // this doesn't compile!
}

但是,当我从 some_algorithm 的参数中删除 const 时,它编译得很好。

有人有想法可以帮助我吗?

标签: c++rangec++20

解决方案


推荐阅读