c++ - 由于 operator= 不明确,multi_index_container 不适用于递归变体

标签 c++ boost boost-variant boost-multi-index

假设我们想要使用动态 C++ 类型对 C 结构建模。 IE。我们有一组字段,每个字段都有一个名称和一个值。该值可以是简单的基本类型(为了示例,我们只说 int)或其他结构,即另一组字段。

这很简单:

template <typename RecursiveVariant>
struct Field
{
    std::string      name;
    RecursiveVariant value;
};

template <typename RecursiveVariant>
using StructFields = std::vector<Field<RecursiveVariant>>;

typedef typename boost::make_recursive_variant<
    int
  , StructFields<boost::recursive_variant_>
  >::type FieldValue;

int main(int argc, char* argv[])
{
    FieldValue fv = 2;
    StructFields<FieldValue> sf;
    Field<FieldValue> f{"name", 2};
    sf.push_back(f);
    fv = sf;

    return 0;
}

它按预期工作。但是,如果我们尝试使用 multi_index_container 而不是 std::vector,它将无法编译。如果我将 StructFields 的定义更改为:

template <typename RecursiveVariant>
using StructFields = multi_index_container<
    Field<RecursiveVariant>
  , indexed_by<
        sequenced<>
      , ordered_unique<
            member<
                Field<RecursiveVariant>
              , std::string
              , &Field<RecursiveVariant>::name
              >
          >
      >
  >;

编译器(来自 VS 15.6.3 的 MSVC)将发出

二进制“=”:未找到接受类型为“boost::multi_index::multi_index_container,boost::multi_index::multi_index_container, ...”的右手操作数的运算符

在线投诉 fv = sf。它提示 variant& operator=(const variant& rhs)variant& operator=(variant&& rhs) 之间的歧义。我不确定这些 operator= 是如何参与的。有解决这个问题的方法吗?

最佳答案

与@sehe 一样,我怀疑问题与 Boost.MPL 魔术(特别是所谓的占位符表达式的识别)有关,但不知道为什么会失败。

FWIW,替换 using StructFields带有硬类型定义的位似乎可以解决问题:

template <typename RecursiveVariant>
struct StructFields: multi_index_container<
    Field<RecursiveVariant>
  , indexed_by<
        sequenced<>
      , ordered_unique<
            member<
                Field<RecursiveVariant>
              , std::string
              , &Field<RecursiveVariant>::name
              >
          >
      >
  >{};

或者,更好的是,只对索引执行硬类型技巧:

template <typename RecursiveVariant>
struct StructFieldsIndices:indexed_by<
    sequenced<>
  , ordered_unique<
        member<
            Field<RecursiveVariant>
          , std::string
          , &Field<RecursiveVariant>::name
          >
      >
  >{};

template <typename RecursiveVariant>
using StructFields = multi_index_container<
    Field<RecursiveVariant>
  , StructFieldsIndices<RecursiveVariant>
  >;

后记:好的,我想我知道发生了什么。如前所述,使用“更简单”的索引(例如 sequenced)时不会出现问题。或 random_access , 是在扔ordered_unique 的时候因为事情失败了。这三个是索引说明符声明如下:

template <typename TagList=tag<> >
struct sequenced;
template <typename TagList=tag<> >
struct random_access;
template<typename Arg1,typename Arg2=mpl::na,typename Arg3=mpl::na>
struct ordered_unique;

ordered_unique 的特殊性是它的mpl::na默认值:在定义 StructFields<boost::recursive_variant_> 的上下文中,Boost.MPL“看到”那些mpl::na通过 ordered_unique层并且无法将整个类型识别为具有一个 arg 的占位符表达式。

后记:我现在真的觉得这是怎么回事:-)而且它与mpl::na无关(实际上,sequenced 在其默认的 mpl::na = tag<> 参数中隐藏了 tag<mp::na,...,mpl::na> 并且不会引发任何错误)。问题与 &Field<RecursiveVariant>::name 有关arg member以及 Boost.MPL 无法替代 &Field<FieldValue>::name对于 &Field<boost::recursive_variant_>::name在处理占位符表达式时(我猜是因为这是一个非类型 模板参数)。因此,您可以将硬类型技巧限制为仅定义 member如下:

template <typename RecursiveVariant>
struct FieldName: member<
    Field<RecursiveVariant>
  , std::string
  , &Field<RecursiveVariant>::name
  >{};

template <typename RecursiveVariant>
using StructFields = multi_index_container<
    Field<RecursiveVariant>
  , indexed_by<
        sequenced<>
      , ordered_unique<FieldName<RecursiveVariant>>
      >
  >;

关于c++ - 由于 operator= 不明确,multi_index_container 不适用于递归变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49371896/

相关文章:

c++ - 编译 C++ 源代码以获得最大的可移植性

c++ - 在复制构造函数中执行深复制

c++ - 从 boost::threaded 成员函数获取返回值?

c++ - boost::get boost::variant 没有给出正确的输出

C++:寻找 "returning address of local variable..."的更正

c++ - 循环内的c++线程会打印错误的值

C++ Boost 正则表达式与标准库正则表达式匹配结果

c++ - boost::multi_array 内存管理和作用域

c++ - boost::apply_visitor 不是 [some] 类的成员

c++ - boost 变体对常用方法的简单调用