Pergunta

Eu preciso criar um mapa, desde inteiros para conjuntos de tuplos, as tuplas em um único conjunto têm o mesmo tamanho. O problema é que o tamanho de uma tupla e seus tipos de parâmetro pode ser determinado em tempo de execução, não tempo de compilação. Eu estou imaginando algo como:

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

mas não exctly certeza de como fazer exatamente isso, bossibly usando ponteiros.

O objetivo deste é criar relações temporárias (tabelas), cada um com um identificador exclusivo (chave), talvez você tenha uma outra abordagem.

Foi útil?

Solução

O objetivo da boost::tuple é misturar tipos arbitrários. Se, como você diz,

Eu só estou inserindo números inteiros

então você deve usar map< int, set< vector< int > > >. (Se eu fosse você, eu iria jogar alguns typedefs naquele.)

Para responder à pergunta original, porém, boost::tuple não permite tipos arbitrários em tempo de execução. boost::any faz. No entanto, any não suporta comparação por isso há um pouco mais de trabalho, se você quiser usá-lo em um 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;

Outras dicas

Como um moderno nota lateral (como respostas anteriores são circa 2010), de hoje variádicos Modelos seria útil para isso:

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

Você só pode armazenar esses diferentes conjuntos na mesma coleção se você tem alguma classe base comum para eles. Você poderia escrever uma interface abstrata, e, em seguida, implementar que, para cada tipo de mesa / tupla. O problema é que, geralmente, essas interfaces tendem a ser muito confuso, e você possivelmente teria classe de explosão se você tem muitos tipos de mesa / tuplas. Boost.Any poderia ser útil para tal uma interface (desde que você tem que lidar com diferentes tipos de dados dinamicamente).

Se os tipos de parâmetro têm algo em comum, captura que em uma classe base abstrata e fazer as tupla contêm ponteiros para esta classe base:

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

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

(boost :: tuple omitido por brevidade. Não sei por que você precisa de um conjunto de tuplas.)

Você, então, pode derivar os tipos de parâmetro concreto de MyParamBase e criar e inseri-las no mapa:

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;

Se os tipos de parâmetro não tem nada em comum - não colocá-los no mesmo mapa. Muito provavelmente eles não pertencem juntos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top