Вектор с различными типами, определенными во время компиляции

Мой вопрос довольно короткий:

Мне нужен вектор, который содержит разные типы, например:

std::vector<int,double> vec;
vec.emplace_back((int) 1);
vec.emplace_back((double) 2.0);

Я пытался использовать boost: variant, но проблема в том, что каждый раз, когда вы хотите использовать значения, нужно посещать/извлекать числа из вектора.

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

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

double d=vec[1]*3.0; //this should somehow work
int i=vec[0]*8;      //this also without any get or anything

Я пытался использовать кортежи, но у меня нет большого опыта работы с ними, и мне кажется, что перебирать их довольно сложно.

for(auto &elem : vec) std::cout << elem << std:endl; //this or sth. similar should also work

Любая помощь приветствуется.


person hdijohkem    schedule 02.07.2015    source источник
comment
Это невозможно без чего-то вроде boost::variant или его разновидности.   -  person AnT    schedule 03.07.2015
comment
@AnT Вы имеете в виду какой-то вариант этого? хар хар   -  person Barry    schedule 03.07.2015
comment
Либо, как сказал @Ant, либо вам нужно иметь общий базовый класс и хранить указатели или интеллектуальные указатели. Но даже тогда вам придется dynamic_cast() и т. д., если у классов нет ничего общего. Если вам требуется перегрузить operator<< и operator*, необходимые операции будут каким-то образом работать.   -  person namezero    schedule 03.07.2015
comment
У меня почему-то возникает ощущение, что этот вектор не является хорошим инструментом для основной проблемы в первую очередь (конечно, просто предположение, поскольку я не знаю основной проблемы). Вы, вероятно, должны либо иметь два вектора, либо получить фактический тип данных прямо.   -  person Baum mit Augen    schedule 03.07.2015
comment
В вашем примере вы можете просто использовать вектор двойников.   -  person ApproachingDarknessFish    schedule 03.07.2015
comment
@TuttiFruttiJacuzzi: Тогда сделайте один из типов std::string - если хотите.   -  person hdijohkem    schedule 03.07.2015
comment
Ваши ints и doubles всегда будут храниться вместе как пары?   -  person Galik    schedule 03.07.2015
comment
Нет, также может быть больше типов, таких как int, double, std::string.   -  person hdijohkem    schedule 03.07.2015


Ответы (1)


Вы действительно должны использовать кортеж. CPP — язык со строгой типизацией. Смирись с этим.

Теперь, если вы хотите повторить, рассмотрите возможность использования Boost Fusion:

Жить на Coliru

#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>

#include <boost/phoenix.hpp>

using namespace boost;
using namespace boost::phoenix::arg_names;

#include <iostream>

int main() {
    tuple<int, double, std::string> demo(42, 3.1415, "hello pie universe");

    fusion::for_each(demo, std::cout << arg1 << "\n");

    auto& v2 = get<1>(demo);
    v2 *= 10;
    std::cout << "\nNew v2: "         << v2   << "\n";
    std::cout << "Tuple after edit: " << demo << "\n";
}

Какие печатает

42
3.1415
hello pie universe

New v2: 31.415
Tuple after edit: (42 31.415 hello pie universe)
person sehe    schedule 02.07.2015
comment
Можете ли вы объяснить, как мне получить, например, второе значение, чтобы сделать с ним расчет? И могу ли я изменить значения, не меняя тип, и это все еще работает? - person hdijohkem; 03.07.2015
comment
Если я восприму ваш комментарий буквально, то да, и: демо - person sehe; 03.07.2015
comment
Возможно, упомянуть, что этого можно добиться с помощью С++ 11 без вызова boost? - person Gerard; 03.07.2015
comment
@ Джерард Я не знаю эквивалента для fusion::for_each в С++ 11 (да, выражение феникса можно заменить полиморфной лямбдой (С++ 14) или объектом полиморфной функции; кортеж может быть std::tuple просто Я также не думаю, что std::tuple реализуют операторы потоковой передачи ввода-вывода) - person sehe; 03.07.2015