0

I've got a persistence class like:

class Writer: private boost::noncopyable {
    template<typename T>
    struct Record {
        std::vector<T> _queued; // waiting to be persisted
        hsize_t _fileRows; // on disk
        DataSet _ds;
        ...
    };

    template<typename T>
    void write(Writer::Record<T>& rcrd) { ... }
    ...

That is used to persist Types such as:

struct A {
    sockaddr_in udpAddr;
    ...
}

struct B {
    uint8_t id;
    ...
}

struct C { ... }
...

I can't change the APIs above and I want to perform bulk operations on these heterogeneous types. I'm using boost::variant with partial success, following their own tutorial:

typedef boost::variant< Record<A>, Record<B>, Record<C>, ...> _types;
std::vector<_types> _records;

struct CloseRecordVisitor : public boost::static_visitor<> {
    template <typename T>
    void operator()(T& operand) const {
        assert(operand._queued.empty());
        operand._ds.close();
    }
}; // This seems to work -template argument is substituted with Record<A>, Record<B>,...

struct WriteRecordVisitor : public boost::static_visitor<> {
    template <typename T>
    void operator()(T& operand) const {
        Writer::write(operand);
    }
}; // This never compiles

Then the bulk operations across all the (many) heterogeneous types was meant to do simply:

CloseRecordVisitor _closeRecordVisitor;
std::for_each(_records.begin(), _records.end(), boost::apply_visitor(_closeRecordVisitor));

WriteRecordVisitor _writeRecordVisitor;
std::for_each(_records.begin(), _records.end(), boost::apply_visitor(_writeRecordVisitor));

WriteRecordVisitor doesn't compile. Error is

No matching function to call ...template substitution failed. Cannot convert 'operand' (type Writer::Record<A>) to type 'Writer::Record<Record<A>>&'

Which evidently looks wrong but I can't figure out what's causing it.

I'd like to either have the WriteRecordVisitor approach working or be able to iterate through the vector (obtaining boost::variant<...>) and somehow (template again, likely) use boost::get to pass each appropriate element (Record<A>, Record<B>, ...) to Writer::write(Record<T>).

I'd also like to avoid defining a visitor operator for each possible heterogeneous type, as that would defeat the original goal of simplifying using an heterogeneous container in the 1st place.

I'm using gcc 4.7.2 on Linux 3.5.4 Fedora 17. Any help is appreciated -I did read all the other posts on boost::variant before posting.

jorgetown
  • 455
  • 3
  • 12
  • Actually `operand` in your Visitor only takes `T` and not `template` which your `write` function takes. Not sure if you can make a visitor which takes a template. – Tony The Lion May 08 '13 at 15:29
  • Thank you for the answer, Tony The Lion. I see that on the error message but my question is why is the Visitor generating nested templates. There's also no possible Writer implementation for Record< Record > -that simply has no meaning as we don't persist nested records and don't know what to do with one. – jorgetown May 08 '13 at 15:41
  • Its the fact that your `write` expects a `Record` and you give it a non-template instead, which is `T&` essentially. – Tony The Lion May 08 '13 at 15:43
  • 1
    `write(operand)` is wrong. There is no free function of that name, and `WriteRecordVisitor` does not have one such member. There is also a missing semicolon, which indicates the code you are posting does is not the code you are compiling. Please do not do that. – R. Martinho Fernandes May 08 '13 at 15:57
  • Well, R. Martinho Fernandes...I wouldn't do it but sometimes depends on the policies of your employer. In my case, the development hosts are not connected to the Internet. I tried to be thorough but without copy-paste things do slip and these are large classes. But thanks for your remark anyways. Also, the visitors are on the same class that extends the Writer class. – jorgetown May 08 '13 at 16:18
  • 2
    I don't care. Without code that accurately reproduces the error, we are left with guessing. Many people prefer to not waste time with that. No one is asking you to post code you cannot post. You can produce some isolated code that causes the same error, and then you can post it verbatim and we can properly understand what is going on. – R. Martinho Fernandes May 08 '13 at 16:22

0 Answers0