简体   繁体   English

如何实现自己的功能到std :: vector?

[英]How to implement own function to std::vector?

I would like to add a function that returns the .size() value as an integer, instead of unsigned integer. 我想添加一个将.size()值返回为整数而不是无符号整数的函数。

Edit: Due to comments, i explain more detailed: 编辑:由于评论,我解释更详细:

I have code: 我有代码:

int something = 3;
if(arr.size() > something) 

Which will produce compiler warning, and i dislike adding (int) to every place where i have this. 这将产生编译器警告,我不喜欢在每个有此地方的地方都添加(int)。 So, a solution i thought it would be nice to have sizei() function: 所以,我认为有一个解决方案,最好有sizei()函数:

int something = 3;
if(arr.sizei() > something) 

Which wouldnt produce a warning. 哪一个不会产生警告。

So, im not wanting to create a separate function, but a function in the std::vector itself. 因此,即时通讯不想创建一个单独的函数,而是要在std :: vector本身中创建一个函数。

Edit: Seems like the only way to do this is to create another function, such as: 编辑:似乎唯一的方法是创建另一个函数,例如:

template <typename T>
inline int sizei(const T &arr){
    return (int)arr.size();
}

On the positive side: this doesnt seem to increase my executable size at all. 从积极的一面:这似乎并没有增加我的可执行文件的大小。

First of all, why would you want that? 首先,为什么要那样? I don't see any reason, or advantage: 我看不出任何原因或优势:

Anyway, you can do this: 无论如何,您可以执行以下操作:

template<typename T>
int size(const std::vector<T> &v) { return (int) v.size(); }

//use
std::vector<int> ints;
//...
int count = size(ints);

Still I don't see any point in doing that. 我仍然看不到这样做的任何意义。 You can simply write: 您可以简单地写:

int count = (int) ints.size(); 

But I would still say its not better than the following : 但是我仍然会说它并不比以下更好:

size_t count = ints.size(); //don't prefer anything over this. Always use size_t

Advice: avoid using int for size. 建议:避免将int用作大小。 Prefer size_t . 更喜欢size_t


As for the edit in your question. 至于您的问题中的编辑。 Why don't you use size_t as: 为什么不使用size_t作为:

size_t something = 3;
if(arr.size() > something) 

No warning. 没有警告。 In my opinion, if you choose the data type consistently throughout your program, you wouldn't come across a situation when you've to compare int with size_t which is defined as unsigned integral type. 我认为,如果在整个程序中始终选择数据类型,则在将int与定义为无符号整数类型的size_t进行比较时,不会遇到任何情况。

Or if there is some legacy code which you've to work with, and which use int for size, then I think its better to use explicit cast when you need it, instead of adding a function in the framework itself, which hides the potential problem: 或者,如果有一些旧代码需要使用,并且使用int作为大小,那么我认为最好在需要时使用显式强制转换,而不是在框架本身中添加函数,这样可以隐藏潜在的问题问题:

int something = /*some legacy code API call or something */;
if(arr.size() > (size_t) something) 

//or even better;
size_t something = (size_t) /*some legacy code API call or something */;
if(arr.size() > something) 

As a rule, in C and C++ you should never use an unsigned type such as size_t to restrict the domain. 通常,在C和C ++中,永远不要使用无符号类型(如size_t来限制域。 That's because (1) these languages provide no range checking, and (2) they do provide unreasonable implicit promotions. 这是因为(1)这些语言不提供范围检查,(2)它们确实提供了不合理的隐式提升。 No range checking means (1) no advantage, and unreasonable implicit promotions means (2) very undesirable disadvantages, so it's plain stupid thing to do: no advantage, very undesirable disadvantages. 没有范围检查手段(1)没有优势,没有合理的隐式提升手段(2)非常不希望的劣势,因此这是愚蠢的事情:没有优势,就非常不利的劣势。

However, the standard libraries for these languages do that. 但是,这些语言的标准库可以做到这一点。 They do it for historical reasons only, caught irreversibly in early decisions which at one time made sense. 他们这样做只是出于历史原因 ,不可逆转地陷入了一次明智的早期决策中。 This has both extremely silly consequences such as C99 requiring 17 (!) bits for ptrdiff_t , and it has the aforementioned extremely undesirable consequences such as using inordinately much time on hunting down bugs resulting from implicit promotions (etc.). 这既有极其愚蠢的后果,例如C99需要ptrdiff_t需要17(!)位,又有上述极为不利的后果,例如花费大量的时间来寻找隐式升级引起的错误(等)。 For example, in C++ you are practically guaranteed that std::string( "bah!" ).length() < -5 – which can easily trip you up and anyway is as silly as it is possible to design. 例如,在C ++中,实际上可以保证std::string( "bah!" ).length() < -5 - std::string( "bah!" ).length() < -5 –可以很容易地使您绊倒,并且无论如何设计都很愚蠢。

Now, you can't infuse new member functions in std::vector , but you can add a freestanding function. 现在,您不能在std::vector注入新的成员函数,但是可以添加一个独立的函数。 A good name is countOf . 好名字是countOf Template it so that it can be applied to just about anything (raw arrays, vectors, etc.). 对其进行模板化,以便可以将其应用于几乎所有内容(原始数组,向量等)。

The triad of functions startOf , endOf and countOf were, as far as I know, first identified by Dietmar Kuehl. 据我所知,函数startOfendOfcountOf组首先由Dietmar Kuehl标识。 C++0x will have std::begin and std::end , but AFAIK no corresponding std::size . C ++ 0x将具有std::beginstd::end ,但AFAIK没有对应的std::size In the meantime you can just define this support, which allows you to treat any kinds of container plus raw arrays the same. 同时,您只需要定义此支持,就可以将任何类型的容器以及原始数组都视为相同。

An example implementation & further discussion is provided at my blog . 我的博客中提供了示例实现和进一步的讨论。


EDIT Adding some code, because it's requested in the comments. 编辑添加一些代码,因为它在注释中被请求。

Detection of suitable iterator type: 检测合适的迭代器类型:

template< typename Type >
struct It
{
    typedef typename Type::iterator T;
};

template< typename Type >
struct It< Type const >
{
    typedef typename Type::const_iterator T;
};

template< typename ElemType, Size N >
struct It< ElemType[N] >
{
    typedef ElemType* T;
};

And the countOf , startOf and endOf functions, using that deduced iterator type: 以及countOfstartOfendOf函数,使用推导的迭代器类型:

template< typename T >
inline Size countOf( T const& c )           { return static_cast<Size>( c.size() ); }

template< typename T, Size N >
inline Size countOf( T (&)[N] )             { return N; }

template< typename T >
inline typename It<T>::T startOf( T& c )    { return c.begin(); }

template< typename T, Size N >
inline T* startOf( T (&a)[N] )              { return a; }

template< typename T >
inline typename It<T>::T endOf( T& c )      { return c.end(); }

template< typename T, Size N >
inline T* endOf( T (&a)[N] )                { return a + N; }

where Size is a typedef for ptrdiff_t . 其中Sizeptrdiff_t的typedef。

Note: in 64-bit Windows int (and even long ) is 32-bit. 注意:在64位Windows中, int (甚至是long )是32位。 Hence, int is in general not sufficient for a really large array. 因此,对于大数组而言, int通常是不够的。 ptrdiff_t is guaranteed to be able to represent the difference between any two pointers, when that difference is well-defined. 当明确定义了ptrdiff_t的差异时,可以保证它能够表示任何两个指针之间的差异。


Cheers & hth. 干杯和健康。

I would favor using an explicit cast to int instead of a function: static_cast<int> (v.size()) . 我希望使用显式static_cast<int> (v.size())int而不是函数: static_cast<int> (v.size()) Even better would be to always use size_t when dealing with memory sizes. 更好的做法是在处理内存大小时始终使用size_t For example, favor for (size_t i=0; i < v.size(); ++i) over for (int i=0; i < (int) v.size(); ++i) . 例如, for (int i=0; i < (int) v.size(); ++i)偏爱for (size_t i=0; i < v.size(); ++i) for (int i=0; i < (int) v.size(); ++i) Use the right type for the job. 为作业使用正确的类型。 You should not be comparing std::vector sizes with a signed type. 您不应将std :: vector大小与带符号类型进行比较。

See the following references for why you should prefer size_t to int: 请参阅以下参考资料,以了解为什么您应该首选size_t而不是int:

You can derive from vector as follows: 您可以从向量派生如下:

template<typename T>
class my_vector : public vector<T>
{
  // missing constructors!

  int size() const
  {
    if (vector<T>::size() > INT_MAX)
      throw std::range_error("too many elements in vector");
    return (int) vector<T>::size();
  }
};

The down-side is that you'll have to define and forward constructors yourself. 缺点是您必须自己定义和转发构造函数。

Quick answer for .size() is: no. .size()的快速答案是:不。 For vectors, the possibilities are its storage value and the alloc method (default new / delete , not normally overridden) along with methods that utilize InputIterator . 对于矢量,可能性是它的存储值和alloc方法(默认为new / delete ,通常不会被覆盖)以及利用InputIterator方法。

Most are going to ask why would you want a different size_t . 大多数人会问你为什么要换一个不同的size_t If it's just the annoy warnings, you can cast or use unsigned integers to iterate/check against size(). 如果只是烦人的警告,则可以强制转换或使用无符号整数对size()进行迭代/检查。 (If it's a lot of code, you going to have to find/replace)... If it is handling empty conditions, you could wrap the vector in a class with some smarts. (如果代码很多,则必须查找/替换)...如果它处理空条件,则可以将矢量包装在具有某些智能的类中。 As an aside, since I don't know your problem at hand, a good place to look for ideas and already implemented features is std library's algorithms such as sort , for_each , find , and lots more. 顺便说一句,由于我不知道您手头的问题,因此,寻找想法和已经实现的功能的好地方是std库的算法,例如sortfor_eachfind和更多。

For std algorithms, see: http://www.sgi.com/tech/stl/table_of_contents.html 有关std算法的信息,请参见: http : //www.sgi.com/tech/stl/table_of_contents.html

While @Nawaz, in my opinion, provided the most appropriate answer, if you really want to add an additional member to std::vector<> it isn't really possible. 我认为@Nawaz提供了最合适的答案,但是,如果您真的想向std :: vector <>添加其他成员,则实际上是不可能的。 @zvrba provided the only way that could be accomplished, but as stated in the comments there the std container types do not have virtual destructors and therefore are not meant to be subclassed from. @zvrba提供了唯一可以实现的方法,但是正如注释中所述,std容器类型没有虚拟析构函数,因此不应从其子类化。

However, you could implement a new type of vector using a container adaptor, like this: 但是,您可以使用容器适配器来实现一种新型的矢量,如下所示:

template <class T>
class my_vector
{
public:
   int size_i() const
   {
      return static_cast<int>(container_.size());
   }

private:
   std::vector<T> container_;
};

The drawback here is that you have to explicitly expose the functions of the container that you actually need to support. 这里的缺点是您必须显式公开您实际需要支持的容器的功能。 If you are using 'std::vector' normally throughout your code, this would likely be a significant change. 如果您在整个代码中通常使用“ std :: vector”,则可能会发生重大变化。 See 'std::queue' for an implementation example of a container adaptor. 有关容器适配器的实现示例,请参见“ std :: queue”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM