对于 std::begin ,我们有两个容器重载:
std::begin
template< class C > auto begin( C& c ) -> decltype(c.begin()); template< class C > auto begin( const C& c ) -> decltype(c.begin());
但是 C 的常量可以通过通常的模板推导规则来推断,所以看起来第二次重载是多余的 . 我错过了什么?
C
在rvalue上调用 begin (以及 end )是合理的,前提是我们在容器被销毁后不使用生成的迭代器 . 但是,将rvalue传递给 T& 形式的参数将不起作用,这是第二次重载发挥作用的地方 .
begin
end
T&
然而,很可能我们正在处理一个前range-based for proposal wording的轻率转变:
将以下内容添加到[container.concepts.member]的末尾:template <Container C> concept_map Range <C> {typedef C :: iterator iterator;iterator begin(C&c){return Container <C> :: begin(c); }迭代器结束(C&c){return Container <C> :: end(c); }};
template <Container C> concept_map范围<const C> {typedef C :: const_iterator iterator;iterator begin(const C&c){return Container <C> :: begin(c); }iterator end(const C&c){return Container <C> :: end(c); }};
当很明显概念不会进入C 11时,论文被修改,并且所有四个函数temploids都可能被翻译成等效的命名空间范围函数模板 . 这会导致rvalues被接受(可能是非预期的)后果,而原始代码只是为了区分不同的合格容器类型 .
请注意, begin / end 的现代实现将使用转发引用 - 例如
template <typename T> constexpr auto begin(T&& t) -> decltype(std::forward<T>(t).begin()) { return std::forward<T>(t).begin(); }
1 回答
在rvalue上调用
begin
(以及end
)是合理的,前提是我们在容器被销毁后不使用生成的迭代器 . 但是,将rvalue传递给T&
形式的参数将不起作用,这是第二次重载发挥作用的地方 .然而,很可能我们正在处理一个前range-based for proposal wording的轻率转变:
template <Container C> concept_map范围<const C> {
typedef C :: const_iterator iterator;
iterator begin(const C&c){return Container <C> :: begin(c); }
iterator end(const C&c){return Container <C> :: end(c); }};
当很明显概念不会进入C 11时,论文被修改,并且所有四个函数temploids都可能被翻译成等效的命名空间范围函数模板 . 这会导致rvalues被接受(可能是非预期的)后果,而原始代码只是为了区分不同的合格容器类型 .
请注意,
begin
/end
的现代实现将使用转发引用 - 例如