Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate a vector with unique values?

I have this example to generate unique objects into a vector :

#include <iostream>
#include <vector>
#include <algorithm>

int v=0;

struct A
{
    A() : refValue( v++)
    { std::cout<<"constructor refValue="<<refValue<<std::endl; }
    A( const A &r ) : refValue(r.refValue)
    { std::cout<<"copy constructor refValue="<<refValue<<std::endl; }
    A& operator=( const A &r )
    {
        refValue = r.refValue;
        std::cout<<"operator= refValue="<<refValue<<std::endl;
        return *this;
    }
    ~A() { std::cout<<"destructor refValue="<<refValue<<std::endl; }

    int refValue;
};

A GenerateUnique()
{
    A unique;
    return unique;
}
struct B
{
    B( const int n) : v()
    {
        std::generate_n( std::back_inserter( v ), n, &GenerateUnique );
    }
    std::vector< A > v;
};

int main()
{
    B b(3);
}

If I change my main into this :

struct B
{
    B( const int n) : v(n)
    {
    }
    std::vector< A > v;
};

then one object of type A will be copied into all vector elements.

Is there a way to create a vector with all unique objects (like in the 1st example)?

To make it more clear : I have a class containing a vector. This vector must contain all unique objects (not a copy of one object). And I would like to initialize it in the initialization list (not in the body of the constructor).

like image 668
BЈовић Avatar asked Jul 28 '11 07:07

BЈовић


2 Answers

Your first attempt is the one that works.

In the current standard C++03 this line

std::vector< A > as( n ); 

is explicitly defined to create one A object and copy that n times.

I belive that in C++0x this is changed to create n default constructed As (a small difference). Then you might perhaps be able to do something in As constructor to make each instance unique.

Right now you cannot.

like image 188
Bo Persson Avatar answered Sep 18 '22 10:09

Bo Persson


It gets copied because that constructor's signature is as follows:

​explicit vector( size_type count,
             const T& value = T(),
             const Allocator& alloc = Allocator());

It is evident that you just pass a default-constructed object to this constructor and it copies it.

If you want to initialize in the initializer list, you are limited to constructors of some objects, obviously. I guess, you wouldn't like to create a wrapper class just to initialize the vector in initializer list, soo we are limited to vector's constructors. The only one that seems reasonable is

template <class InputIterator>

vector( InputIterator first, InputIterator last,
        const Allocator& alloc = Allocator() );

So you can create an iterator to return the needed number of default-constructed objects.

I suggest just constructing in the constructor body though.

like image 34
unkulunkulu Avatar answered Sep 20 '22 10:09

unkulunkulu