(另请参阅是否有一种很好的方法可以在C++中为自定义类型手写所有12个所需的Container函数?)
对于像这样的课程
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; }
};
}
Run Code Online (Sandbox Code Playgroud)
暴露迭代的首选方式是什么?我应该写begin()/ end()(和cbegin()/ cend())成员函数吗?
const int* cbegin() const {
return get();
}
const int* cend() const {
return cbegin() + size();
}
Run Code Online (Sandbox Code Playgroud)
或者这些应该是非会员职能?
const int* cbegin(const C& c) {
return c.get();
}
const int* cend(const C& c) {
return cbegin(c) + c.size();
}
Run Code Online (Sandbox Code Playgroud)
应该begin()/ end()有两个const和非const过载?
const int* begin() const {
return get();
}
int* begin() {
return get();
}
Run Code Online (Sandbox Code Playgroud)
还有其他事情需要考虑吗?是否有工具/技术使这个"容易正确"并减少锅炉板代码的数量?
一些相关问题/讨论包括:
如果您希望它们与STL一致,那么有一个标准描述了您的类接口应该是什么样子.C++具有"概念"这一概念,它将给定类的要求限定为概念的充分实现.这几乎成了c ++ 11中的语言特性.
您可能感兴趣的概念是容器概念.正如你所看到的,以满足集装箱观的要求,需要begin,cbegin,end,和cend为成员函数(除其他事项外).
由于您将数据存储在数组中,因此您可能也对SequenceContainer感兴趣.
我建议创建两组函数——成员函数和非成员函数——以实现最大的灵活性。
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(); }
}
Run Code Online (Sandbox Code Playgroud)
如果您希望能够使用类型的对象C作为std::begin、std::end、std::cbegin和 的参数,则成员函数是必需的std::cend。
如果您希望能够使用类型的对象C作为begin、end、cbegin和 的参数,则非成员函数是必需的cend。ADL 将确保找到此类用途的非成员函数。
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)