Кортежи неизвестного размера / типов параметров

StackOverflow https://stackoverflow.com/questions/2416653

  •  19-09-2019
  •  | 
  •  

Вопрос

Мне нужно создать карту, от целых чисел до наборов кортежей, кортежи в одном наборе имеют одинаковый размер.Проблема в том, что размер кортежа и типы его параметров могут быть определены во время выполнения, а не во время компиляции.Я представляю себе что-то вроде:

std::map<int, std::set<boost::tuple> >

но не совсем уверен, как именно это сделать, властно используя указатели.

Целью этого является создание временных связей (таблиц), каждая из которых имеет уникальный идентификатор (ключ), возможно, у вас есть другой подход.

Это было полезно?

Решение

Цель boost::tuple заключается в смешивании произвольных типов.Если, как вы говорите,

Я вставляю только целые числа

тогда вам следует использовать map< int, set< vector< int > > >.(На твоем месте я бы бросил немного typedefs при этом.)

Однако, чтобы ответить на первоначальный вопрос, boost::tuple не допускает произвольных типов во время выполнения. boost::any делает.Однако, any не поддерживает сравнение, поэтому потребуется немного больше работы, если вы хотите использовать его в set.

typedef vector< boost::any > tuple;
struct compare_tuple { bool operator()( tuple const &l, tuple const &r ) const {
    assert ( l.size() == r.size() );

    for ( tuple::iterator lit = l.begin(), rit = r.begin();
          lit != l.end(); ++ lit, ++ rit ) {
        assert ( lit->type() == rit->type() );

        if ( lit->type() == typeid( foo ) ) { // find the type and perform "<"
            return boost::any_cast<foo>(*lit) < boost::any_cast<foo>(*rit);
        } else if ( lit->type() == typeid( bar ) ) {
            return boost::any_cast<bar>(*lit) < boost::any_cast<bar>(*rit);
        } /* etc; you will need to enumerate all the types you can insert */
    }
} };

typedef std::map< int, std::set< tuple, compare_tuple > > main_map;

Другие советы

В качестве современного примечания (поскольку предыдущие ответы относятся примерно к 2010 году), для этого были бы полезны сегодняшние шаблоны Variadic:

template<typename... Args> //Accept any number of arguments and types
auto MyFunction(std::tuple<Args...> &T)->void
{
   //Do stuff...
}

Вы можете хранить эти разные наборы в одной коллекции, только если у вас есть какой-то общий базовый класс для них.Вы могли бы написать абстрактный интерфейс, а затем реализовать его для каждого типа таблицы / кортежа.Проблема в том, что обычно такие интерфейсы имеют тенденцию быть очень запутанными, и у вас, возможно, произошел бы взрыв класса, если бы у вас было много типов таблиц / кортежей. Повышение.Любое может быть полезно для такого интерфейса (поскольку вам приходится динамически обрабатывать разные типы данных).

Если типы параметров имеют что-то общее, перенесите это в абстрактный базовый класс и сделайте так, чтобы кортеж содержал указатели на этот базовый класс:

class MyParamBase {
public:
    virtual int getFoo() = 0;
    virtual void setFoo(int) = 0;
};

std::map<int, std::set<MyParamBase*> > container;

(boost::кортеж опущен для краткости.Не уверен, зачем вам нужен набор кортежей.)

Затем вы можете получить конкретные типы параметров из MyParamBase, создать и вставить их в map:

class SomeParam: MyParamBase {
public:
    virtual int getFoo() { ... }
    virtual void setFoo(int a) { ... }
};

std::set<MyParamBase*> some_set;
some_set.insert(new SomeParam());
container[123] = some_set;

Если типы параметров не имеют ничего общего - не помещайте их в одну и ту же карту.Вполне вероятно, что они не принадлежат друг другу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top