使用标准范围时,对 'end' 的引用不明确
reference to 'end' is ambiguous when using std ranges
当我尝试编译以下代码时:
// This file is a "Hello, world!" in C++ language by GCC for wandbox.
#include <iostream>
#include <cstdlib>
#include <ranges>
#include <vector>
#include <numeric>
#include <cmath>
template <typename T>
struct Foo
{
std::vector<T> vec;
auto begin() { return vec.begin(); }
auto end() { return vec.end(); }
auto begin() const { return vec.cbegin(); }
auto end() const { return vec.cend(); }
auto size() const { return vec.size(); }
};
namespace std::ranges
{
template <typename T>
auto begin(Foo<T>& x) { return x.begin(); }
template <typename T>
auto end(Foo<T>& x) { return x.end(); }
template <typename T>
auto begin(const Foo<T>& x) { return x.begin(); }
template <typename T>
auto end(const Foo<T>& x) { return x.end(); }
}
template <std::ranges::range range>
void some_algorithm(const range& r)
{
return std::accumulate(std::ranges::begin(r), std::ranges::end(r), 0);
}
int main()
{
}
我收到一条错误消息:
include/vector.h:93:78: error: reference to 'end' is ambiguous
93 | return std::sqrt(std::accumulate(std::ranges::begin(range), std::ranges::end(range), 0));
| ^~~
In file included from c:\mingw64\include\c++.2.0\string:54,
from c:\mingw64\include\c++.2.0\bits\locale_classes.h:40,
from c:\mingw64\include\c++.2.0\bits\ios_base.h:41,
from c:\mingw64\include\c++.2.0\ios:42,
from c:\mingw64\include\c++.2.0\ostream:38,
from c:\mingw64\include\c++.2.0\iostream:39,
from main.cpp:1:
c:\mingw64\include\c++.2.0\bits\range_access.h:846:42: note: candidates are: 'constexpr const std::ranges::__cust_access::_End std::ranges::__cust::end'
846 | inline constexpr __cust_access::_End end{};
| ^~~
In file included from main.cpp:8:
include/vector.h:71:8: note: 'template<class T, long long unsigned int N> auto std::ranges::end(const vec<T, N>&)'
71 | auto end(const vec<T, N>& v)
“开始”也一样。我知道错误消息的含义,但我真的不明白为什么会这样。我什至没有启动模板,那么它为什么要检查调用呢?我有点困惑,有人可以帮助我吗?
std::ranges::begin
不是函数;它是一个函数 object。你不能专门化它或重新定义它。这是 故意。
在 std
命名空间中专门化 begin/end
的旧标准方法不是 Ranges 的工作方式,它是 专门 设计的,以阻止您这样做那。创建范围的方法是定义成员 begin/end
函数或在范围类型的命名空间中定义 ADL-capable begin/end
函数。
同样,愚蠢的 using std::begin; begin(rng);
习语不是您调用 ranges::begin
的方式。您可以通过...调用 std::ranges::begin
来调用它。因为这就是您应该调用函数的方式。
当我尝试编译以下代码时:
// This file is a "Hello, world!" in C++ language by GCC for wandbox.
#include <iostream>
#include <cstdlib>
#include <ranges>
#include <vector>
#include <numeric>
#include <cmath>
template <typename T>
struct Foo
{
std::vector<T> vec;
auto begin() { return vec.begin(); }
auto end() { return vec.end(); }
auto begin() const { return vec.cbegin(); }
auto end() const { return vec.cend(); }
auto size() const { return vec.size(); }
};
namespace std::ranges
{
template <typename T>
auto begin(Foo<T>& x) { return x.begin(); }
template <typename T>
auto end(Foo<T>& x) { return x.end(); }
template <typename T>
auto begin(const Foo<T>& x) { return x.begin(); }
template <typename T>
auto end(const Foo<T>& x) { return x.end(); }
}
template <std::ranges::range range>
void some_algorithm(const range& r)
{
return std::accumulate(std::ranges::begin(r), std::ranges::end(r), 0);
}
int main()
{
}
我收到一条错误消息:
include/vector.h:93:78: error: reference to 'end' is ambiguous
93 | return std::sqrt(std::accumulate(std::ranges::begin(range), std::ranges::end(range), 0));
| ^~~
In file included from c:\mingw64\include\c++.2.0\string:54,
from c:\mingw64\include\c++.2.0\bits\locale_classes.h:40,
from c:\mingw64\include\c++.2.0\bits\ios_base.h:41,
from c:\mingw64\include\c++.2.0\ios:42,
from c:\mingw64\include\c++.2.0\ostream:38,
from c:\mingw64\include\c++.2.0\iostream:39,
from main.cpp:1:
c:\mingw64\include\c++.2.0\bits\range_access.h:846:42: note: candidates are: 'constexpr const std::ranges::__cust_access::_End std::ranges::__cust::end'
846 | inline constexpr __cust_access::_End end{};
| ^~~
In file included from main.cpp:8:
include/vector.h:71:8: note: 'template<class T, long long unsigned int N> auto std::ranges::end(const vec<T, N>&)'
71 | auto end(const vec<T, N>& v)
“开始”也一样。我知道错误消息的含义,但我真的不明白为什么会这样。我什至没有启动模板,那么它为什么要检查调用呢?我有点困惑,有人可以帮助我吗?
std::ranges::begin
不是函数;它是一个函数 object。你不能专门化它或重新定义它。这是 故意。
在 std
命名空间中专门化 begin/end
的旧标准方法不是 Ranges 的工作方式,它是 专门 设计的,以阻止您这样做那。创建范围的方法是定义成员 begin/end
函数或在范围类型的命名空间中定义 ADL-capable begin/end
函数。
同样,愚蠢的 using std::begin; begin(rng);
习语不是您调用 ranges::begin
的方式。您可以通过...调用 std::ranges::begin
来调用它。因为这就是您应该调用函数的方式。