暴露自定义STL样式迭代的首选方法是什么? [英] what is the preferred way to expose custom STL-style iteration?
问题描述
(另见是否有一种很好的方法可以在C ++中手动编写自定义类型的所有12个所需容器函数?)
对于类等
namespace JDanielSmith {
class C
{
const size_t _size;
const std::unique_ptr<int[]> _data;
public:
C(size_t size) : _size(size), _data(new int[size]) {}
inline const int* get() const noexcept { return _data.get(); }
inline int* get() noexcept { return _data.get(); }
size_t size() const noexcept { return _size; }
};
}
公开迭代的首选方式是什么?我应该写 begin()
/ end()
(和 cbegin()
/ cend()
)成员函数?
what is the preferred way to expose iteration? Should I write begin()
/end()
(and cbegin()
/cend()
) member functions?
const int* cbegin() const {
return get();
}
const int* cend() const {
return cbegin() + size();
}
或者这些是非会员功能吗?
or should these be non-member functions?
const int* cbegin(const C& c) {
return c.get();
}
const int* cend(const C& c) {
return cbegin(c) + c.size();
}
应该 begin()
/ end()
同时具有 const
和非 const
重载?
Should begin()
/end()
have both const
and non-const
overloads?
const int* begin() const {
return get();
}
int* begin() {
return get();
}
还有其他需要考虑的事项吗?是否有工具/技术使这个容易变得正确并减少锅炉板代码的数量?
Are there any other things to consider? Are there tools/techniques to make this "easy to get right" and reduce the amount of boiler-plate code?
一些相关的问题/讨论包括:
Some related questions/discussion include:
- Should custom containers have free begin/end functions?
- Why use non-member begin and end functions in C++11?
- When to use
std::begin
andstd::end
instead of container specific versions
推荐答案
我建议创建两组函数 - 成员函数和非成员函数 - 以允许最大化灵活性。
I suggest creating both sets of functions -- member functions as well as non-member functions -- to allow for maximum flexibility.
namespace JDanielSmith {
class C
{
const size_t _size;
const std::unique_ptr<int[]> _data;
public:
C(size_t size) : _size(size), _data(new int[size]) {}
inline const int* get() const { return _data.get(); }
inline int* get() { return _data.get(); }
size_t size() const { return _size; }
int* begin() { return get(); }
int* end() { return get() + _size; }
const int* begin() const { return get(); }
const int* end() const { return get() + _size; }
const int* cbegin() const { return get(); }
const int* cend() const { return get() + _size; }
};
int* begin(C& c) { return c.begin(); }
int* end(C& c) { return c.end(); }
const int* begin(C const& c) { return c.begin(); }
const int* end(C const& c) { return c.end(); }
const int* cbegin(C const& c) { return c.begin(); }
const int* cend(C const& c) { return c.end(); }
}
如果你想要能够使用的对象,必须使用成员函数输入 C
作为 std :: begin
, std :: end $ c的参数$ c>,
std :: cbegin
和 std :: cend
。
The member functions are necessary if you want to be able to use objects of type C
as arguments to std::begin
, std::end
, std::cbegin
, and std::cend
.
如果您希望能够使用 C
类型的对象作为 begin <的参数,则必须使用非成员函数/ code>,
结束
, cbegin
, cend
。 ADL将确保为这些用法找到非成员函数。
The non-member functions are necessary if you want to be able to use objects of type C
as arguments to just begin
, end
, cbegin
, and cend
. ADL will make sure that the non-member functions will be found for such usages.
int main()
{
JDanielSmith::C c1(10);
{
// Non-const member functions are found
auto b = std::begin(c1);
auto e = std::end(c1);
for (int i = 0; b != e; ++b, ++i )
{
*b = i*10;
}
}
JDanielSmith::C const& c2 = c1;
{
// Const member functions are found
auto b = std::begin(c2);
auto e = std::end(c2);
for ( ; b != e; ++b )
{
std::cout << *b << std::endl;
}
}
{
// Non-member functions with const-objects as argument are found
auto b = begin(c2);
auto e = end(c2);
for ( ; b != e; ++b )
{
std::cout << *b << std::endl;
}
}
}
这篇关于暴露自定义STL样式迭代的首选方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!