Denis
Denis

Reputation: 1534

map of ints to class (template)

I would like to write some class which maps int to something using templates. What I'm thinking of are generally two options:

1. unsigned int ->  double          (scalar)
2. unsigned int ->  double[N]       (vector of length N; N is the same for each int)

I write a class around

template <class T>
class int2type_storage {
  public:
    ....
  private:
    typename std::map<unsigned int,T> map_;
}

With the first case, the usage is straightforward:

int2type_storage<double> map1;

The question is, what is the most efficient way/object for the second case? I was thinking to do something like

 int2type_storage< std::vector<double> >

but I have a feeling that this will be sub-optimal. Another option is to store pointers

 int2type_storage< double* >

but then I have a problem that I should allocate memory for N elements outside of the map-class and take care to free it later.

EDIT1: Thank you guys for answering, I feel sorry that I can't mark two answers as correct.

EDIT2:

I have implemented everything, but my linker could not find functions:

undefined reference to `int2type_storage<std::tr1::array<double, 4ul> >::init(int, int)'

.h:

template <class T>
class int2type_storage {
public:
    int2type_storage() {};
    ~int2type_storage() {};

    void init(const int number, const int index);
        ...
private:
    int cur_index_;
    typename std::map<unsigned int, T>::iterator iterator_;
    typename std::vector<std::map<unsigned int,T> > map_vector_;
    bool zero_initialized;
};

.cpp:

template<class T>
void int2type_storage< T >::init(const int length, const int max_index) {
    map_vector_.resize(length);
}

usage:

int2type_storage< std::tr1::array<double, 4> > w_map_;

what's wrong?

Upvotes: 0

Views: 136

Answers (2)

Steve Jessop
Steve Jessop

Reputation: 279315

If you have C++11, std::array is the best, and there's also Boost.Array.

If you don't, then you can write something like:

template <size_t N>
struct Doubles {
    double data[N];
};

Then either directly use .data to access it, or add as many member functions and operator overloads as you want. If you add the right ones then eventually you'll have std::array.

The main sensible use for double* is if you are copying maps (or otherwise have multiple maps), and you want them to refer to the same data. But as you already know, it creates a resource-management problem, so you could consider shared_array<double>. You could also consider not sharing data.

There's also a possible special case, that in C++03 elements get copied into containers, whereas in C++11 there's a potential efficiency gain by moving them into the container in some circumstances. But arrays (including std::array and my class above) cannot efficiently be moved. If N is large, and there's a lot of copying going on, then potentially something that is efficiently movable might work better, so you could again consider std::vector.

Upvotes: 3

juanchopanza
juanchopanza

Reputation: 227468

Assumming N is known at compile-time, you could use an std::array<double,N>:

int2type_storage< std::array<double, N> >

I am not sure what the reasons for the int2type_storage wrapper are, but you could also use a C++11 template typedef:

template <typename T, int N>
using int2type_storage = std::map<unsigned int, std::array<T,N>>;

Upvotes: 4

Related Questions