Я работаю с довольно неудобным c-интерфейсом для хранения коллекций. Класс LowLevelStorer
представляет собой оболочку, которую я написал для этого интерфейса. Класс Storer
- класс высокого уровня, который относится к Data
. Он кэширует и связывает данные с более сложными типами данных, известными только LowLevelStorer
. Остальная часть моего кода работает только с Data
и не знает об LowLevelData
.boost :: variant members подмножество другого boost :: variant
В приведенном ниже примере кода я хочу, чтобы члены в варианте Data
были включены в вариант LowLevelData
. Есть ли способ указать это другое, как я это сделал?
Я действительно не понимаю, почему приведенный ниже код компилируется и действительно, почему он действительно работает правильно. То есть void operator()(const SimplePath&, const Data& data) const
берет ссылку на данные, но, кажется, правильно преобразовывает ее в объект LowLevelData при вызове void operator()(const LowLevelData& data) const
. Как это может быть?
Есть ли много копий, которые здесь происходят за кулисами в отношении моих объектов данных?
#include "boost/variant.hpp"
#include "boost/variant/apply_visitor.hpp"
#include <vector>
class Complex{};
typedef boost::variant< std::vector<Complex>, std::vector<int>, std::vector<std::string> > LowLevelData;
class LowLevelStorer
{
public:
LowLevelStorer(): _storeVisitor(StoreVisitor()){}
void operator()(const LowLevelData& data) const
{
boost::apply_visitor(_storeVisitor, data);
}
private:
class StoreVisitor: public boost::static_visitor<>
{
public:
void operator()(const std::vector<Complex>&) const {}
void operator()(const std::vector<int>& i) const {}
void operator()(const std::vector<std::string>&) const {}
};
StoreVisitor _storeVisitor;
};
struct SimplePath{};
struct BundlePath{};
typedef boost::variant< SimplePath, BundlePath > Path;
typedef boost::variant< std::vector<std::string>, std::vector<int> > Data;
class Storer
{
public:
Storer(const LowLevelStorer& lowLevelStorer): _converter(Converter(lowLevelStorer)){}
void operator()(const Path& path, const Data& data) const
{
boost::apply_visitor(_converter, path, data);
}
private:
class Converter: public boost::static_visitor<>
{
public:
Converter(const LowLevelStorer& lowLevelStorer): _lowLevelStorer(lowLevelStorer){}
void operator()(const SimplePath&, const Data& data) const {
_lowLevelStorer(data);
}
void operator()(const BundlePath&, const Data& data) const {
_lowLevelStorer(std::vector<Complex>());
}
private:
const LowLevelStorer _lowLevelStorer;
};
const Converter _converter;
};
int main()
{
Storer storer((LowLevelStorer()));
std::vector<int> v;
v.push_back(13);
storer(Path(SimplePath()),v);
return 0;
}
Это в значительной степени это - данные гарантированно содержат объект, который будет вписываться в LowLevelData. – Puppy
@Tony The Lion Мне все еще нужны два варианта, так как вариант Data не содержит std :: vector. Этот элемент используется интерфейсом низкого уровня, но я хочу, чтобы он был скрыт от интерфейса высокого уровня. –
Baz
@Baz, то почему бы не иметь вариант с двумя другими типами и передать вектор «Complex» в качестве отдельного аргумента, где это необходимо? –