boost :: variant访问者返回错误(最烦恼的解析?)

时间:2016-03-31 23:12:05

标签: c++ c++11 gcc boost boost-variant

我有一个std::array boost::variant个对象,我正在尝试创建一个boost::static_visitor来访问数组中的元素,并返回对每个元素的引用变体成员类型。这是一个满口的,所以这里是一个模仿我的实现的代码片段:

#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;
  }
}

这段代码用clang 3.6.2编译,但gcc 5.3.1吐出以下内容(后面是来自boost变量头的几十个错误)

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);

所有错误似乎都说同样的事情 - 访问者的返回类型为void,我无法将其绑定到SomeType&。我不认为我的SomeVisitor实现有任何语法错误,因为这样可以很好地处理clang。

This questionthis question显示boost::static_visitor生成的类似错误,两者都是由C ++最烦恼的解析解释的。在这两个问题中,问题都是这样的(使用上面我的代码片段中的类型):

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

在这种情况下,我可以理解最令人烦恼的解析是如何应用的。 MyVariant variant(A());可能对编译器不明确。我不知道这是如何适用于我的代码片段的,因为MyVariant& variant = variants_[index]似乎很明确。我不知道这些问题是否与我的问题有关。

任何建议/帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

评论作为答案提供:

您必须在static_visitor的模板参数列表中指定返回类型。将它留空是告诉编译器该仿函数将返回void。

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

或者,在使用c ++ 14的boost的更高版本中:

auto& something = boost::apply_visitor([](auto& x) { return x.someMethod(); }, 
                                       variant);