首先尝试从1到n的std :: vector [英] First try at a std::vector from 1 to n

查看:65
本文介绍了首先尝试从1到n的std :: vector的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




大家好


我想创建一个std :: vector,从1到n而不是0到n- 1.

这将是唯一的变化是循环,当向量返回

元素的位置等。我现在称之为uovec(对于

Unit-Offset VECtor)。我希望课程能够正确回应

STL容器和算法的所有用法,以便它是

std:vector的透明替代品。


选项似乎是:


1)从std :: vector公开派生,然后定义operator(),但我相信
相信那个std :: vector并不打算用作基类所以没有

虚拟析构函数(可能还有其他陷阱)虽然在这种情况下我是

不会需要在派生类中存储任何成员,所以这可能会没有区别吗?


2)将std :: vector存储在内部并将其用作必要 - 这似乎是

的首选。


3)其他?从std :: vector和界面私下导出?


无论如何我怀疑需要管家才能保留STL容器

和算法快乐。 />

几年前,我在列表中询问了这些问题并获得了几个有用的回复,但却被其他任务分散了注意力并放弃了C ++。

我现在回来了(并做好了准备),我对这次

首次尝试的批评感兴趣。它使用(2)但我不确定是否涵盖了所有必需的STL

行为,所以我有直接访问

包含std的getout子句: :向量。我宁愿避免这样做。


模板< class T>

//////////////// /////////////////

// uovec - std:vector< T>但是使用单位偏移量运算符()

//可以添加其他东西以使其完全像std :: vector

//可以调用v.foo()或者必要时使用vref()但不是很优雅

//////////////////////////////// /

class uovec {

typedef std :: vector< T> vT;


静态const iter offset = 1;

vT v;


public:

//简单构造函数

uovec(const iter s):v(s){}

uovec(const iter s,const T fill):v( s,fill){}


//复制构造函数和赋值将是必需的但不在此处给出


//从1到n的访问

内联T& operator()(const iter i){return v [i-offset]; }

inline const T& operator()(const iter i)const {return v [i-offset]; }


inline vT& vref(){return v; } //返回对v的引用

case复杂的STL需要...讨厌

inline const vT& vref()const {return v; } //返回const引用

const v


//向量迭代器

typename vT :: iterator begin(){ return v.begin(); } $ / $
typename vT :: iterator end(){return v.end(); } $ / $
typename vT :: const_iterator begin()const {return v.begin(); } $ / $
typename vT :: const_iterator end()const {return v.end(); }


typename vT :: reverse_iterator rbegin(){return v.rbegin(); }

typename vT :: reverse_iterator rend(){return v.rend(); } $ / $
typename vT :: const_reverse_iterator rbegin()const {return v.rbegin(); } $ / $
typename vT :: const_reverse_iterator rend()const {return v.rend(); }


};

Michael


_ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ /


_ / _ / _ / _ / _ / Hopkins Research Ltd

_ / _ / _ / _ /

_ / _ / _ / _ / _ / _ / _ / http://www.hopkins-research.com/

_ / _ / _ / _ /

_ / _ / _ / _ /''触摸未来''

_ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ / _ /


[见 http://www.gotw .ca / resources / clcm.htm 有关的信息]

[comp.lang.c ++。moderated。第一次海报:做到这一点! ]

解决方案

Michael Hopkins写道:


3)其他?私有地从std :: vector和界面中获取?




我没想过太多,但我想我会得到

私下并使用using指令转发所有那些

相同的东西:


模板< typename T,int offset = 1>

类uovec:std :: vector< T>

{

public:

使用std :: vector< T> ::开始;

使用std :: vector< T> :: end;

使用std :: vector< T> :: rbegin;

使用std :: vector< T> :: rend;


T& operator [](int i){return std :: vector< T> :: operator [](i - offset); }

T const& operator [](int i)const {return

std :: vector< T> :: operator [](i - offset); }

};


注意我也做了一个模板参数的偏移,使这更加有趣,你可以拥有你喜欢的任何偏移。我也更喜欢

使用下标运算符over operator(),但那只是我。


请务必打开标准并提供一个完整的界面。


HTH

Neal


[见 http://www.gotw.ca/resources/clcm.htm 了解有关的信息]

[comp.lang.c ++。moderated。第一次海报:做到这一点! ]


" Michael Hopkins" < MI ************* @ hopkins-research.com>在消息中写道

新闻:BE9D1446.3BD00%mi ************* @ hopkins-research.com ...

我想创建一个从1到n而不是0到n-1的std :: vector。
这将有唯一的变化是循环和向量返回元素的位置我现在称之为uovec(对于
Unit-Offset VECtor)。我希望课程能够正确回应STL容器和算法的所有用法,以便它是
std:vector的透明替代品。



我不明白这是怎么回事。毕竟,如果v是std :: vector,那么

v [0]定义得很好 - 但你建议定义一个v [0]
$的类b $ b定义不明确。所以它不可能是一个透明的替代品。

[见 http://www.gotw.ca/resources/clcm.htm 有关的信息]

[comp.lang.c ++。moderated。第一次海报:做到这一点! ]


Michael Hopkins写道:

大家好

我想要创建一个std :: vector,从1到n而不是0到n-1。


您可能想要从A到B,其中A和B是任意的(并且在构造函数时指定)。

选项似乎是:

1)从std :: vector公开派生,然后定义operator(),但我相信std :: vector是不打算用作基类所以没有虚拟析构函数(可能还有其他陷阱)虽然在这种情况下我不需要在派生类中存储任何成员,所以这可能会<没有区别?


不过,这会有问题 - 例如我的建议

以上;在初始版本只有1到N之后,可能有人会添加

功能并不是很牵强。然后,你

可能会开始进入麻烦,因为未来版本可能会无意中打破你的初步假设。


但更具体地说,你仍然会遇到未定义的

行为,即使你测试并测试它,它总是表现为你期望和想要的b / b
2)在里面存储一个std :: vector并将其用作必要 - 这似乎是首选的选择。


我会这么说。

3)其他?私有地从std :: vector和接口派生?


嗯,我闻到了麻烦的可能性......因为你必须提供很多

元素的vector'接口/>
界面,并且具有完全相同的名称(你想要一个透明

替换矢量,对吗?),然后每当你提供一个
$ b $其中b,你可能最终隐藏其他成员从现在的私人

无障碍界面,并可能随之而来的惊喜...我将不会出现

麻烦只需添加一个矢量作为数据成员并将您的

界面映射到您的矢量数据成员。

无论如何我怀疑需要管家才能保留STL容器
和算法快乐。




提供所有迭代器 - 作为typedef:


模板< typename T>

类Ovector

{

public:

typedef T value_type;

typedef vector< ; T> :: iterator iterator;

typedef vector< T> :: const_iterator const_iterator;

// ...与其他人相同(reverse_iterator等)


iterator begin(){return d_vector.begin(); } $ / $
const_iterator begin()const {return d_vector.begin(); }

iterator end(){return d_vector.end(); } $ / $
const_iterator end()const {return d_vector.end(); }

// ...等

我怀疑唯一让你头疼的是

区分构造函数:


模板< typename迭代器>

Ovector(迭代器开始,迭代器结束)


和:


模板< typename T>

Ovector(int size,T value)


当T是int(嗯,那将是size_t,但是让我们把它变成int $ / b $ b来简化事情)。使用vector,因为它是

语言的一部分,编译器可以做一些魔术来消除这个问题的歧义。但是对于你正在创建的一个类,我想唯一的

解决方案是为所有

可能的积分tyepes提供专门的类定义! (哎哟:-()


当然,另一个解决方案是不提供那些(毕竟,你的

构造函数自然会期望一个额外的参数,如果你按照我的建议 - 下标在任意范围内的方式来实现


但这对于矢量来说是否足够透明了?我

猜你只能决定。


HTH,


Carlos

-


[见 http://www.gotw。 ca / resources / clcm.htm 有关的信息]

[comp.lang.c ++。版主。第一次海报:做这个!]




Hi all

I want to create a std::vector that goes from 1 to n instead of 0 to n-1.
The only change this will have is in loops and when the vector returns
positions of elements etc. I am calling this uovec at the moment (for
Unit-Offset VECtor). I want the class to respond correctly to all usage of
STL containers and algorithms so that it is a transparent replacement for
std:vector.

The options seems to be:

1) deriving publicly from std::vector and then define operator(), but I
believe that std::vector is not meant to be used as a base class so no
virtual destructor (and possibly other gotchas) though in this case I
wouldn''t need to store any members in the derived class so maybe this would
make no difference?

2) store a std::vector inside and use it as necessary - this appears to be
the preferred option.

3) other? Deriving privately from std::vector and an interface?

In any case I suspect housekeeping will be required to keep STL containers
and algorithms happy.

A couple of years ago I was asking these questions on the list and got
several helpful replies but got distracted by other tasks and dropped C++.
Am now back (and better prepared) and I was interested in a critique of this
first attempt. It uses (2) but I''m not sure if all the required STL
behaviour is covered so I have the getout clause of direct access to the
contained std::vector. I would prefer to avoid doing this.

template <class T>
/////////////////////////////////
// uovec - a std:vector<T> but with unit-offset via operator ()
// can add other stuff to make it exactly like std::vector
// can call v.foo() or use vref() if necessary but not very elegant
/////////////////////////////////
class uovec {
typedef std::vector<T> vT;

static const iter offset = 1;
vT v;

public:
// simple constructors
uovec ( const iter s ) : v( s ) {}
uovec ( const iter s, const T fill ) : v( s, fill ) {}

// copy constructors and assignments will be required but not given here

// access from 1 to n
inline T& operator() ( const iter i ) { return v[i-offset]; }
inline const T& operator() ( const iter i ) const { return v[i-offset]; }

inline vT& vref () { return v; } // return reference to v in
case complicated STL required... nasty
inline const vT& vref () const { return v; } // return const reference to
const v

// vector iterators
typename vT::iterator begin() { return v.begin(); }
typename vT::iterator end() { return v.end(); }
typename vT::const_iterator begin() const { return v.begin(); }
typename vT::const_iterator end() const { return v.end(); }

typename vT::reverse_iterator rbegin() { return v.rbegin(); }
typename vT::reverse_iterator rend() { return v.rend(); }
typename vT::const_reverse_iterator rbegin() const { return v.rbegin(); }
typename vT::const_reverse_iterator rend() const { return v.rend(); }

};
Michael

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

_/ _/ _/_/_/ Hopkins Research Ltd
_/ _/ _/ _/
_/_/_/_/ _/_/_/ http://www.hopkins-research.com/
_/ _/ _/ _/
_/ _/ _/ _/ ''touch the future''

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

解决方案

Michael Hopkins wrote:


3) other? Deriving privately from std::vector and an interface?



I haven''t thought too much about it, but I think I would derive
privately and use the using directive to forward all those things that
are the same:

template <typename T, int offset = 1>
class uovec : std::vector<T>
{
public:
using std::vector<T>::begin;
using std::vector<T>::end;
using std::vector<T>::rbegin;
using std::vector<T>::rend;

T& operator[](int i) { return std::vector<T>::operator[](i - offset); }
T const& operator[](int i) const { return
std::vector<T>::operator[](i - offset); }
};

Notice I also made offset a template argument to make this even more
interesting, you can then have any offset you like. I also preferred
using the subscript operator over operator(), but that''s just me.

Just be sure to open the standard and provide a complete interface.

HTH
Neal

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


"Michael Hopkins" <mi*************@hopkins-research.com> wrote in message
news:BE9D1446.3BD00%mi*************@hopkins-research.com...

I want to create a std::vector that goes from 1 to n instead of 0 to n-1.
The only change this will have is in loops and when the vector returns
positions of elements etc. I am calling this uovec at the moment (for
Unit-Offset VECtor). I want the class to respond correctly to all usage
of
STL containers and algorithms so that it is a transparent replacement for
std:vector.



I don''t see how that is possible. After all, if v is a std::vector, then
v[0] is well defined--but you''re proposing to define a class in which v[0]
is not well defined. So it can''t possibly be a transparent replacement.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Michael Hopkins wrote:

Hi all

I want to create a std::vector that goes from 1 to n instead of 0 to n-1.
You probably want to make that "from A to B", where A and B are
arbitrary (and specified at constructor-time).
The options seems to be:

1) deriving publicly from std::vector and then define operator(), but I
believe that std::vector is not meant to be used as a base class so no
virtual destructor (and possibly other gotchas) though in this case I
wouldn''t need to store any members in the derived class so maybe this would
make no difference?
Still, it would be asking for trouble -- take for instance my suggestion
above; it''s not far-fetched to think that maybe someone will add that
functionality after your initial version does only 1 to N. Then, you
may start getting in trouble, since future version might inadvertedly
break your initial assumptions.

But more specifically, you would still be incurring in undefined
behaviour, even if you test it and test it and it always behaves as
you expect and want.
2) store a std::vector inside and use it as necessary - this appears to be
the preferred option.
I would say so.
3) other? Deriving privately from std::vector and an interface?
Hmmm, I smell possibilities of trouble... Since there are many
elements of vector''s interface that you have to provide as your
interface, and with the exact same name (you want a "transparent"
replacement for vector, right?), then whenever you provide one
of those, you may end up hiding other members from the now privately
accessible interface, and surprises may ensue... I''d stay out of
trouble by simply adding a vector as data member and mapping your
interface to that of your vector data member.
In any case I suspect housekeeping will be required to keep STL containers
and algorithms happy.



Provide all the iterators -- as typedefs:

template <typename T>
class Ovector
{
public:
typedef T value_type;
typedef vector<T>::iterator iterator;
typedef vector<T>::const_iterator const_iterator;
// ... same for others (reverse_iterator, etc.)

iterator begin() { return d_vector.begin(); }
const_iterator begin() const { return d_vector.begin(); }
iterator end() { return d_vector.end(); }
const_iterator end() const { return d_vector.end(); }
// ... etc.
The only thing I suspect is going to give you a headache is to
make the distinction between the constructors:

template <typename Iterator>
Ovector (Iterator begin, Iterator end)

And:

template <typename T>
Ovector (int size, T value)

When T is int (well, that would be size_t, but let''s make it int
to simplify things). With vector, because it is part of the
language, the compiler is allowed to do some magic to disambiguate
the issue. But with a class that you''re creating, I guess the only
solution would be to provided specialized class definitions for all
possible integral tyepes! (ouch :-( )

Sure, another solution would be not to provide those (after all, your
constructor would naturally expect an extra parameter if you do it
the way I suggested -- subscript being within an arbitrary range).
But would that be a transparent enough replacement for vector? I
guess only you can decide that.

HTH,

Carlos
--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


这篇关于首先尝试从1到n的std :: vector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆