Question

I have a container variant as follows:

typedef boost::variant<std::vector<int>, std::vector<std::string> > Container;

And I populate a Container object from a ValueContainer object (a C struct) as follows:

class ContainerAppender: public boost::static_visitor<>
{
public:
    void setValueToAppend(const Value* value){
        _value = value;
    }

    void operator()(std::vector<int>& container) const {
        container.push_back(_value->value.i);
    }

    void operator()(std::vector<std::string>& container) const {
        container.push_back(_value->value.s);
    }

    ...

private:
    const Value* _value;
};

void fillContainer(Container& container, ValueContainer* cContainer) {
    if(cContainer) {
        ContainerAppender append;
        for(int i = 0; i < cContainer->nunberOfValues; i++) {
            append.setValueToAppend(&cContainer->values[i]);
            boost::apply_visitor(append, container);
        }
    }
}

I am not free to change the C structures.

I don't like my solution for populating the container as I am visiting for every loop despite the fact that the container type never changes. It feels that there is a better way of doing. Can you help?

here's the C union:

typedef struct Value {
    union {
        int   i;
        const char* s;
    } value;
} Value_T;

typedef struct ValueContainer {
    Type type;
    unsigned int numberOfValues;
    Value *values;
} ValueContainer_T;
Was it helpful?

Solution

Is the visitor really necessary? Consider this:

template<typename T>
T value_get(Value_T const &c_variant) {
    return T();
}

template<>
int value_get<int>(Value_T const &c_variant) {
    return c_variant.i;
}

template<>
const char* value_get<const char*>(Value_T const &c_variant) {
    return c_variant.s;
}

template<typename T> 
std::vector<T> fill_vector(ValueContainer_T const& c_container) {
    std::vector<T> cpp_container(c_container.numberOfValues);
    for(size_t i = 0; i < c_container.numberOfValues; ++i)
        cpp_container[i] = value_get<T>(c_container.values[i]);
    return cpp_container;
}

Looks simpler to me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top