Danvil
Danvil

Reputation: 22981

How to mimic template variable declaration

I have a basic type Item<N> which depends on an integer template parameter N and class Data which holds instances of Item<N> for several different N.

Here is an example:

template<unsigned N>
struct Item { ... }; // some template data type

struct Data
{
    std::set<Item<1>> items1;
    std::set<Item<2>> items2;
    std::set<Item<3>> items3;
    std::set<Item<4>> items4;
    std::set<Item<5>> items5;

    bool contains(const Item<1>& x) { return items1.find(x) != items1.end(); }
    bool contains(const Item<2>& x) { return items2.find(x) != items2.end(); }
    bool contains(const Item<3>& x) { return items3.find(x) != items3.end(); }
    bool contains(const Item<4>& x) { return items4.find(x) != items4.end(); }
    bool contains(const Item<5>& x) { return items5.find(x) != items5.end(); }
};

Now with several functions like contains there is a lot of code duplication. Is there a more elegant way to implement Data?

Upvotes: 2

Views: 144

Answers (3)

Jarod42
Jarod42

Reputation: 217145

Following may help:

struct Data
{
    std::tuple<std::set<Item<1>>,
               std::set<Item<2>>,
               std::set<Item<3>>,
               std::set<Item<4>>,
               std::set<Item<5>>> items;

    template <int N>
    bool contains(const Item<N>& x) const {
        static_assert(0 < N && N < 6, "N out of range");
        return std::get<N - 1>(items).find(x) != std::get<N - 1>(items).end();
    }
};

Upvotes: 3

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153820

You could, e.g., store a suitable std::tuple<...> and have your contain() function be a template, e.g.:

template <int... I>
struct DataImpl {
    std::tuple<std::set<Item<I>>...> data;
    template <int J>
    bool contains(Item<J> const& x) {
        return std::get<J-1>(data).find(x) != std::get<J-1>(data).end();
    }
};
using Data = DataImpl<1, 2, 3, 4, 5>;

Upvotes: 3

Kerrek SB
Kerrek SB

Reputation: 476990

How about something with a "type list", like so:

template <unsigned int ...> struct Data;

template <> struct Data<> {};

template <unsigned int N, unsigned int ...Tail>
struct Data : Data<Tail...>
{
    std::set<Item<N>> item;
    bool contains(const Item<N> & x) const { return item.find(x) != item.end(); }
};

Usage:

Data<2, 8, 19> data;   // contains sets of Item<2>, Item<8> and Item<19>

Upvotes: 1

Related Questions