将模式包装为 std::begin; 返回 begin(c); 到函数中
Wrap pattern std::begin; return begin(c); into a function
有没有办法将模式包装成通用的模板函数?
template <typename C>
auto Begin(C&& c) -> ??? {
using std::begin;
return begin(std::forward<C>(c));
}
这里的问题是这里如何编写函数的返回类型?
我想要这个的原因是我想写一个模板变量
template <typename C>
constexpr bool IsBidirectionalContainer =
std::is_base_of<std::bidirectional_iterator_tag,
typename std::iterator_traits<
decltype(std::begin(std::declval<C>()))>::iterator_category>::value;
这里的问题是std::begin
不会找到通过 ADL 进行C
的自定义begin
重载。如果有人对此有解决方法,也欢迎。
你需要把它包装在另一个命名空间中,即:
namespace details {
using std::begin;
template <typename C>
auto Begin(C&& c) -> decltype(begin(std::forward<C>(c)))
{
return begin(std::forward<C>(c));
}
}
然后:
template <typename C>
constexpr bool IsBidirectionalContainer =
std::is_base_of<std::bidirectional_iterator_tag,
typename std::iterator_traits<
decltype(details::Begin(std::declval<C>()))>::iterator_category>::value;
如果出于某种原因您拒绝在命名空间中定义Begin
,则可以使用类型别名来绕过它。
namespace details {
using std::begin;
template <typename C>
using type = decltype(begin(std::forward<C>(c)));
}
template <typename C>
auto Begin(C&& c) -> details::type<C>
{
return begin(std::forward<C>(c));
}
尽管这可能比必要的工作要多。向前声明可能就足够了。
如果你要包装它,我想"为什么不使用最新的最好的想法呢? 具体来说,Eric Niebler 提出了一个论点,即这些应该是函数调用对象,而不是函数!
这是我使用 C++17 编译器的新版本
// ===================
// would be in a reusable header
namespace twostep {
using std::begin;
using std::end;
inline auto Begin = [](auto&& r) -> decltype(begin(std::forward<decltype(r)>(r))) {
return begin(std::forward<decltype(r)>(r));
};
inline auto End = [](auto&& r) -> decltype(end(std::forward<decltype(r)>(r))) {
return end(std::forward<decltype(r)>(r));
};
}
using twostep::Begin;
using twostep::End;
现在,由于这不会取代std::begin
/end
函数的实现,因此我无法获得 Eric 指出的所有好处。 但是,除了充当为我执行两步的包装器之外,就像普通模板函数实现一样,它本身不受 ADL 的影响。
如果我提到有资格twostep::Begin
,那并不重要。 但是,如果我像此列表对全局范围所做的那样将它们导入到我自己的范围内,那么对Begin(r)
的非限定调用肯定会看到我此时可见的调用,并且由于r
中涉及的所有类型,在不同的命名空间中找不到名为Begin
的函数。
相关文章:
- 调用'begin(int [n])'没有匹配函数
- 有没有函数可以在擦除 c++ 中获取 deque.begin() 的 int 值?
- 错误:调用'begin(long double [nPoints])'没有匹配函数;使用硬编码的 int 与整数变量初始化向量
- 使用 std::set 的 .begin() 和 .end() 函数会产生意想不到的结果
- 为什么 free 函数不能在 C 数组上运行,而 std::begin 在某些情况下可以在 C++14 中运行?
- 将模式包装为 std::begin; 返回 begin(c); 到函数中
- C++ 指针上的开始/结束 (arr) - 调用 'begin(int**&)' 没有匹配函数
- 如何使用begin()自由函数
- 成员函数 .begin() 和 std::begin()
- 非成员函数 begin()/cbegin() 及其 constexpr-ness
- 使用 C++11 的 begin() 和 end() 函数通过参数确定数组维度
- 调用 'begin(int**&)' 没有匹配函数
- 避免通用容器中 begin() 和 end() 函数的重复代码
- begin() 和 end() 函数不应该是模板类 Vector 的成员函数吗?
- 迭代一个STL容器,而不是从.begin()函数开始
- Iterator::Begin()函数错误
- 为我的向量包装器和迭代器返回'begin'和'end'函数返回什么?
- C++11 std::begin 不适用于传递给模板函数的 int[]
- 从特定位置调用Upper_bound函数,而不是使用data.begin()
- 依赖begin()函数的Const迭代器