【发布时间】:2016-11-22 16:15:59
【问题描述】:
我正在尝试为使用std::reverse_iterator 的双向迭代器的容器编写通用反向包装器。
但是,当编译器查找 begin(...) 或 end(...) 时,它会说找不到对 reverse_wrapper<CONTAINER>::begin(container) 的匹配函数调用,因为候选者需要 0 个参数,但提供了 1 个参数。
我猜这是因为std::begin(myArray&) 和std::end(myArray&) 不存在。强制它们进入 std 命名空间不起作用(无论如何也不可取)。我还尝试从 reverse_wrapper 中删除 std:: 前缀,但这没有用,并且还会破坏工作中的 std 容器实现。
这似乎是范围解析问题,但我似乎无法解决。我做错了什么?
代码:
#include <iterator>
#include <iostream>
#include <vector>
#define Fn1 0 // std container WORKS
#define Fn2 1 // non-std container DOESN'T WORK
template <typename Container>
struct reverse_wrapper
{
Container& container;
auto begin()
-> std::reverse_iterator< decltype(std::end(container)) >
{
return std::reverse_iterator< decltype(std::end(container)) >(std::end(container));
}
auto end()
-> std::reverse_iterator< decltype(std::begin(container)) >
{
return std::reverse_iterator< decltype(std::begin(container)) >(std::begin(container));
}
};
template <typename Container>
auto reverse(Container&& container)
-> reverse_wrapper<Container>
{
return{ container };
}
struct myArray
{
int elements[5] = {1,2,3,4,5};
};
int* begin(myArray& array) { return &array.elements[0]; }
int* end(myArray& array) { return &array.elements[5]; }
#if Fn1
void fn1()
{
std::vector<int> x = { 1,2,3,4,5 };
for (auto& ix : reverse(x))
{
std::cout << ix << std::endl;
}
std::cout << "-----" << std::endl;
for (auto& ix : x)
{
std::cout << ix << std::endl;
}
}
#endif
#if Fn2
void fn2()
{
myArray x;
for (auto& ix : reverse(x))
{
std::cout << ix << std::endl;
}
std::cout << "-----" << std::endl;
for (auto& ix : x)
{
std::cout << ix << std::endl;
}
}
#endif
int main()
{
#if Fn1
fn1();
#endif
#if Fn2
fn2();
#endif
}
错误:
在“struct reverse_wrapper”的实例化中: 61:30:从这里需要 14:56:错误:没有匹配函数调用“end(myArray&)” 14:56:注:候选人为: 在 /usr/include/c++/4.9/string:51:0 包含的文件中, 来自 /usr/include/c++/4.9/bits/locale_classes.h:40, 来自 /usr/include/c++/4.9/bits/ios_base.h:41, 来自/usr/include/c++/4.9/ios:42, 来自/usr/include/c++/4.9/ostream:38, 来自 /usr/include/c++/4.9/iterator:64, 从1: /usr/include/c++/4.9/bits/range_access.h:68:5: 注意:模板 decltype (__cont.end()) std::end(_Container&) end(_Container& __cont) -> decltype(__cont.end()) ^ /usr/include/c++/4.9/bits/range_access.h:68:5: 注意:模板参数推导/替换失败: /usr/include/c++/4.9/bits/range_access.h:代替'template decltype (__cont.end()) std::end(_Container&) [with _Container = myArray]': 14:56:'struct reverse_wrapper' 需要 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:68:5: 错误:“struct myArray”没有名为“end”的成员 在“struct reverse_wrapper”的实例化中: 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:78:5: 注意:模板 decltype (__cont.end()) std::end(const _Container&) end(const _Container& __cont) -> decltype(__cont.end()) ^ /usr/include/c++/4.9/bits/range_access.h:78:5:注意:模板参数推导/替换失败: /usr/include/c++/4.9/bits/range_access.h:代替'template decltype (__cont.end()) std::end(const _Container&) [with _Container = myArray]': 14:56:'struct reverse_wrapper' 需要 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:78:5:错误:“const struct myArray”没有名为“end”的成员 在“struct reverse_wrapper”的实例化中: 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:97:5: 注意:模板 _Tp* std::end(_Tp (&)[_Nm]) 结束(_Tp (&__arr)[_Nm]) ^ /usr/include/c++/4.9/bits/range_access.h:97:5:注意:模板参数推导/替换失败: 14:56:注意:不匹配的类型 '_Tp [_Nm]' 和 'myArray' 在 /usr/include/c++/4.9/bits/basic_string.h:42:0 包含的文件中, 来自 /usr/include/c++/4.9/string:52, 来自 /usr/include/c++/4.9/bits/locale_classes.h:40, 来自 /usr/include/c++/4.9/bits/ios_base.h:41, 来自/usr/include/c++/4.9/ios:42, 来自/usr/include/c++/4.9/ostream:38, 来自 /usr/include/c++/4.9/iterator:64, 从1: /usr/include/c++/4.9/initializer_list:99:5: 注意:模板 constexpr const _Tp* std::end(std::initializer_list) end(initializer_list __ils) noexcept ^ /usr/include/c++/4.9/initializer_list:99:5:注意:模板参数推导/替换失败: 14:56:注意:“myArray”不是从“std::initializer_list”派生的 20:58:错误:没有匹配函数调用“begin(myArray&)” 20:58:注:候选人是: 在 /usr/include/c++/4.9/string:51:0 包含的文件中, 来自 /usr/include/c++/4.9/bits/locale_classes.h:40, 来自 /usr/include/c++/4.9/bits/ios_base.h:41, 来自/usr/include/c++/4.9/ios:42, 来自/usr/include/c++/4.9/ostream:38, 来自 /usr/include/c++/4.9/iterator:64, 从1: /usr/include/c++/4.9/bits/range_access.h:48:5: 注意:模板 decltype (__cont.begin()) std::begin(_Container&) 开始(_Container& __cont) -> decltype(__cont.begin()) ^ /usr/include/c++/4.9/bits/range_access.h:48:5:注意:模板参数推导/替换失败: /usr/include/c++/4.9/bits/range_access.h:代替'template decltype (__cont.begin()) std::begin(_Container&) [with _Container = myArray]': 20:58:从“struct reverse_wrapper”中需要 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:48:5: 错误:“struct myArray”没有名为“begin”的成员 在“struct reverse_wrapper”的实例化中: 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:58:5: 注意:模板 decltype (__cont.begin()) std::begin(const _Container&) 开始(const _Container& __cont) -> decltype(__cont.begin()) ^ /usr/include/c++/4.9/bits/range_access.h:58:5:注意:模板参数推导/替换失败: /usr/include/c++/4.9/bits/range_access.h:代替'template decltype (__cont.begin()) std::begin(const _Container&) [with _Container = myArray]': 20:58:从“struct reverse_wrapper”中需要 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:58:5:错误:“const struct myArray”没有名为“begin”的成员 在“struct reverse_wrapper”的实例化中: 61:30:从这里需要 /usr/include/c++/4.9/bits/range_access.h:87:5: 注意:模板 _Tp* std::begin(_Tp (&)[_Nm]) 开始(_Tp (&__arr)[_Nm]) ^ /usr/include/c++/4.9/bits/range_access.h:87:5:注意:模板参数推导/替换失败: 20:58:注意:不匹配的类型 '_Tp [_Nm]' 和 'myArray' 在 /usr/include/c++/4.9/bits/basic_string.h:42:0 包含的文件中, 来自 /usr/include/c++/4.9/string:52, 来自 /usr/include/c++/4.9/bits/locale_classes.h:40, 来自 /usr/include/c++/4.9/bits/ios_base.h:41, 来自/usr/include/c++/4.9/ios:42, 来自/usr/include/c++/4.9/ostream:38, 来自 /usr/include/c++/4.9/iterator:64, 从1: /usr/include/c++/4.9/initializer_list:89:5: 注意:模板 constexpr const _Tp* std::begin(std::initializer_list) begin(initializer_list __ils) noexcept ^ /usr/include/c++/4.9/initializer_list:89:5:注意:模板参数推导/替换失败: 20:58:注意:“myArray”不是从“std::initializer_list”派生的 在函数 'void fn2()' 中: 61:30:错误:从“reverse_wrapper”类型的表达式中对“myArray&”类型的引用进行无效初始化 38:6:注意:传递 'int* begin(myArray&)' 的参数 1 61:30:错误:从“reverse_wrapper”类型的表达式中对“myArray&”类型的引用进行无效初始化 39:8:注意:传递 'int* end(myArray&)' 的参数 1【问题讨论】:
-
去掉
std::begin和std::end中的std::,然后在你使用begin和end的地方加上using std::begin; using std::end。在某些情况下,使用自动推导的返回类型而不是尾随返回类型可能会更好 -
@KABoissonneault,是的,我曾想过使用
using std::begin/end,但它在类范围内不起作用,因此返回类型找不到它。我也想过使用自动推导的类型,但这在 VS2013 中不起作用。 -
在命名空间范围内使用它们怎么样?
-
@KABoissonneault,因为这些类在标题中,所以不是最佳的。
myArray只是分散在其他数组实现的占位符,有些在基本范围内,有些在std。 -
好吧,但是在这方面,我还是觉得
myArray应该提供自己的迭代器,然后reverse_wrapper可以简单的委托给容器而不用直接使用reverse_iterator:template <typename Container> struct reverse_wrapper { Container& container; auto begin() { return std::rbegin(container); } auto end() { return std::rend(container); } };跨度>
标签: c++11 visual-studio-2013 iterator reverse-iterator