2013-05-23 1 views
4

Возможно ли в C++ создать вектор нескольких типов? Я хотел бы иметь возможность создавать и перебирать вектор, содержащий много разных типов. Например:C++ Generic Vector

vector<generic> myVec; 
myVec.push_back(myInt); 
myVec.push_back(myString); 
etc... 

Вектор должен иметь возможность хранить различные типы данных. Есть ли другой векторный тип, который я должен использовать в библиотеке C++?

Любое направление приветствуется.

+2

Возможно, есть вектор «boost :: variant». – chris

+2

Другим выбором является 'boost :: any' – dchhetri

+0

не' std :: vector', а 'std :: tuple' (в C++ 11). std :: vector - контейнер однородных типов. –

ответ

7

Вы можете использовать boost::any. Например:

#include <vector> 
#include <boost/any.hpp> 
#include <iostream> 

struct my_class { my_class(int i) : x{i} { } int x; }; 

int main() 
{ 
    std::vector<boost::any> v; 

    v.push_back(42); 
    v.push_back(std::string{"Hello!"}); 
    v.push_back(my_class{1729}); 

    my_class obj = boost::any_cast<my_class>(v[2]); 
    std::cout << obj.x; 
} 

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

#include <vector> 
#include <boost/variant.hpp> 
#include <iostream> 

struct my_class { my_class(int i) : x{i} { } int x; }; 

int main() 
{ 
    typedef boost::variant<int, std::string, my_class> my_variant; 
    std::vector<my_variant> v; 

    v.push_back(42); 
    v.push_back("Hello!"); 
    v.push_back(my_class{1729}); 

    my_class obj = boost::get<my_class>(v[2]); 
    std::cout << obj.x; 
} 

boost::variant также поддерживает посещения. Вы можете определить посетителя, который может обрабатывать все возможные типы в варианте:

struct my_visitor : boost::static_visitor<void> 
{ 
    void operator() (int i) 
    { 
     std::cout << "Look, I got an int! " << i << std::endl; 
    } 

    void operator() (std::string const& s) 
    { 
     std::cout << "Look, I got an string! " << s << std::endl; 
    } 

    void operator() (my_class const& obj) 
    { 
     std::cout << "Look, I got a UDT! And inside it a " << obj.x << std::endl; 
    } 
}; 

И затем вызвать его, как это сделано ниже:

int main() 
{ 
    typedef boost::variant<int, std::string, my_class> my_variant; 
    std::vector<my_variant> v; 

    v.push_back(42); 
    v.push_back("Hello!"); 
    v.push_back(my_class{1729}); 

    my_visitor mv; 
    for (auto const& e : v) 
    { 
     e.apply_visitor(mv); 
    } 
} 

Вот live example. Хорошая вещь о boost::variant заключается в том, что она выполнит проверку времени компиляции, чтобы убедиться, что ваш посетитель может обрабатывать все типы, которые может содержать этот вариант.

+0

Большое спасибо! –

+0

@ChristopherBales: Рад, что я мог бы помочь :) –

+0

К сожалению, для 'boost :: any', похоже, нет хорошего способа получить значение, если вы его не нажмете. –