【问题标题】:Extending boost variant with an MPL list使用 MPL 列表扩展 boost 变体
【发布时间】:2014-12-20 14:48:57
【问题描述】:

我正在尝试为程序提供一种将新对象添加到库中的变体的方法,但我遇到了一些神秘的错误。

#include <boost/mpl/copy.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/list.hpp>
#include <boost/variant/variant.hpp>

struct InternalType1 {};
struct InternalType2 {};

template <typename LocalTypes>
struct Foo
{
  typedef boost::mpl::list<
    InternalType1,
    InternalType2
  > Types;

  typename boost::make_variant_over<
    typename boost::mpl::joint_view<
      Types,
      LocalTypes
    >::type
  >::type container_;

  // typename boost::make_variant_over<
  //   typename boost::mpl::copy<
  //     LocalTypes,
  //     boost::mpl::back_inserter<Types>
  //   >::type
  // >::type container_;
};

struct LocalType1 {};
struct LocalType2 {};

int main()
{
  typedef boost::mpl::list<
    LocalType1,
    LocalType2
  > Types;

  Foo<Types> foo;
}

通过使用mpl::joint_view(我认为这是实现此目的的最有效方法),我收到以下错误:

/usr/local/include/boost/mpl/clear.hpp:29:7: error: implicit instantiation of undefined template

通过取消注释另一个尝试,使用mpl::copy,并将其替换为原来的,错误就会改变:

/usr/local/include/boost/mpl/aux_/push_back_impl.hpp:40:9: error: no matching function for call to 'assertion_failed'

有趣的是,其中有following comment

// should be instantiated only in the context of 'has_push_back_impl';
// if you've got an assert here, you are requesting a 'push_back' 
// specialization that doesn't exist.

这些错误对我来说都没有任何意义,因为第一个,我看不出哪些模板不完整,第二个,我没有使用哪个 push_back 专业化?

【问题讨论】:

  • 第二个很容易理解,mpl::list不能和push_back一起使用。您可以使用boost::mpl::front_inserter&lt;Types&gt; 或在Types typedef 中使用mpl::vector
  • 啊啊,就是这样。谢谢!由于joint_view 解决方案可能更好,或者两者在生产中做的更好,我会留下这个问题。
  • 除非您打算修改make_variant_over,否则我看不到更好的方法。 mpl::copy from mpl::vectors 是你问我的方式
  • 那么joint_view 在这里不可行吗?它在make_variant_over 的文档中说它需要一个 MPL 序列。然后joint_view 文档声明joint_view 是一个前向序列。所以这两个应该是兼容的吧?

标签: c++ boost metaprogramming boost-mpl


【解决方案1】:

问题是boost::mpl::clear&lt;&gt; 没有为joint_view 实现...因此巨大的编译器转储以:

/usr/local/include/boost/mpl/clear.hpp:29:7: error: implicit instantiation of undefined template 'boost::mpl::clear_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::list<InternalType1, InternalType2, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::list<LocalType1, LocalType2, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> > >'

(我不知道如何正确格式化)

这可能只是库中的一个疏忽,或者可能只是不清楚在这种情况下应该返回哪个空序列类型。如果您想使用joint_view,则必须在某处提供clear_impl 的专业化:

namespace boost { namespace mpl {
   template <>
   struct clear_impl<aux::joint_view_tag>
   {
       template <typename JV>
       struct apply {
           typedef list<> type; // since you're using list I figured
                                // I would too.
       };
   };
} }

这样,您的代码可以在 gcc 和 clang 上为我编译。

或者,如果在namespace boost::mpl 中添加内容让您觉得有点可疑,但您仍想坚持使用lists,您可以使用insert_range

typename boost::make_variant_over<
    typename boost::mpl::insert_range<
        Types,
        typename boost::mpl::end<Types>::type,
        LocalTypes
    >::type
>::type container_;

【讨论】:

  • 好像是这样,谢谢!我想,考虑到这一点,mpl::copympl::vector 听起来确实是最好的选择。就像你说的,一个空的mpl::joint_view 真的没有任何意义......
  • @SamKellett 实际上也可以使用与vector 相同的insert_range 元函数。无论哪种方式,你最终都会得到同样的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-14
相关资源
最近更新 更多