jeudi 31 mars 2016

boost::variant visitor return error (most vexing parse?)

I have an std::array of boost::variant object, and I'm trying to create a boost::static_visitor which visits an element in the array, returning a reference to something in each of the variant member types. That's a mouthful, so here's a code snippet mimicking my implementation:

#include <boost/variant.hpp>
#include <array>

struct SomeType {};

struct A {
  SomeType something;
  SomeType& someMethod() { return something; }
};

struct B {
  SomeType something;
  SomeType& someMethod() { return something; }
};

struct C {
  SomeType something;
  SomeType& someMethod() { return something; }
};

typedef boost::variant<A, B, C> MyVariant;

class SomeVisitor : public boost::static_visitor<> {
public:
  template<typename T>
  SomeType& operator()(T& operand) const {
    return operand.someMethod();
  }
};

class MyVariants {
public:
  SomeType* getSomething(unsigned index);

private:
  static const size_t count = 100;
  std::array<MyVariant, count> variants_;
};

SomeType* MyVariants::getSomething(unsigned index) {
  if(index < count) {
    MyVariant& variant = variants_[index];
    SomeType& something = boost::apply_visitor(SomeVisitor(), variant);
    return &something;
  }
  else {
    return nullptr;
  }
}

This snippet compiles with clang 3.6.2, but gcc 5.3.1 spits out the following (followed by a few dozen errors from the boost variant headers)

test.cpp:43:47: error: invalid initialization of non-const reference of type 'SomeType&' from an rvalue of type 'boost::static_visitor<>::result_type {aka void}'
     SomeType& something = boost::apply_visitor(SomeVisitor(), variant);

All the errors seem to say the same thing - the visitor's return type is void, and I can't bind that to a SomeType&. I don't think there are any syntax errors with my implementation of SomeVisitor since this compiles fine with clang.

This question and this question show similar errors generated by a boost::static_visitor, and both were explained by C++'s most-vexing-parse. In both those questions, the issue was something like this (using types from my snippet above):

MyVariant variant(A());
SomeType& something = boost::apply_visitor(SomeVisitor(), variant);

In this context, I can understand how the most vexing parse applies. MyVariant variant(A()); might be ambiguous to the compiler. I don't know how this applies to my snippet though, since MyVariant& variant = variants_[index] seems pretty explicit. I don't know if these questions are even related to my issues.

Any advice/help would be appreciated

Aucun commentaire:

Enregistrer un commentaire