【问题标题】:Unable to access template objects using boost::apply_visitor无法使用 boost::apply_visitor 访问模板对象
【发布时间】:2016-05-18 18:13:49
【问题描述】:

我正在学习 boost::variant 并使用 apply_visitor 访问其成员。所以,我写了下面的例子。 我有指向模板化对象的指针作为我的类成员。我想使用 apply_visitor 访问它们。

//Example program
#include <iostream>
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
#include <boost/any.hpp>

class A {
    template<size_t dim>
    struct C : boost::static_visitor<C<dim> *>{
        int x;
        C() {
          x = dim;
        }
        template <size_t t>
        C<t> * operator()(C<t> *s) const {
          std::cout<<s->x<<std::endl;
          return s;
        }
    };
 public: 
    C<1>* Aasd;
    C<2>* Bbsd;
    std::map<std::string, boost::variant<C<2> *, C<1> * > > matrices;    

    A() {
        Aasd = new C<1>;
        Bbsd = new C<2>;
    matrices.insert(std::make_pair("Bb", Bbsd));

   boost::apply_visitor(C<2>(), matrices["Bb"]);
   //   boost::apply_visitor(C<1>(), matrices["Aa"]);
   }

    ~A() {
     delete Aasd;
     delete Bbsd;
    }        
};

int main()
{    
  A a;
  return 0;
}

我从上面编译得到的错误是

In file included from /usr/include/boost/variant.hpp:17:0,
                 from 8:
/usr/include/boost/variant/variant.hpp: In instantiation of 'boost::detail::variant::invoke_visitor<Visitor>::result_type boost::detail::variant::invoke_visitor<Visitor>::internal_visit(T&, int) [with T = A::C<1ul>*; Visitor = const A::C<2ul>; boost::detail::variant::invoke_visitor<Visitor>::result_type = A::C<2ul>*]':
/usr/include/boost/variant/detail/visitation_impl.hpp:130:9:   required from 'typename Visitor::result_type boost::detail::variant::visitation_impl_invoke_impl(int, Visitor&, VoidPtrCV, T*, mpl_::true_) [with Visitor = boost::detail::variant::invoke_visitor<const A::C<2ul> >; VoidPtrCV = void*; T = A::C<1ul>*; typename Visitor::result_type = A::C<2ul>*; mpl_::true_ = mpl_::bool_<true>]'
/usr/include/boost/variant/detail/visitation_impl.hpp:173:9:   required from 'typename Visitor::result_type boost::detail::variant::visitation_impl_invoke(int, Visitor&, VoidPtrCV, T*, NoBackupFlag, int) [with Visitor = boost::detail::variant::invoke_visitor<const A::C<2ul> >; VoidPtrCV = void*; T = A::C<1ul>*; NoBackupFlag = boost::variant<A::C<2ul>*, A::C<1ul>*>::has_fallback_type_; typename Visitor::result_type = A::C<2ul>*]'
/usr/include/boost/variant/detail/visitation_impl.hpp:256:5:   required from 'typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = mpl_::int_<0>; step0 = boost::detail::variant::visitation_impl_step<boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<2l>, A::C<2ul>*, boost::mpl::l_item<mpl_::long_<1l>, A::C<1ul>*, boost::mpl::l_end> > >, boost::mpl::l_iter<boost::mpl::l_end> >; Visitor = boost::detail::variant::invoke_visitor<const A::C<2ul> >; VoidPtrCV = void*; NoBackupFlag = boost::variant<A::C<2ul>*, A::C<1ul>*>::has_fallback_type_; typename Visitor::result_type = A::C<2ul>*; mpl_::false_ = mpl_::bool_<false>]'
/usr/include/boost/variant/variant.hpp:2367:13:   required from 'static typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor_impl(int, int, Visitor&, VoidPtrCV) [with Visitor = boost::detail::variant::invoke_visitor<const A::C<2ul> >; VoidPtrCV = void*; T0_ = A::C<2ul>*; T1 = A::C<1ul>*; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_; typename Visitor::result_type = A::C<2ul>*]'
/usr/include/boost/variant/variant.hpp:2378:13:   required from 'typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::internal_apply_visitor(Visitor&) [with Visitor = boost::detail::variant::invoke_visitor<const A::C<2ul> >; T0_ = A::C<2ul>*; T1 = A::C<1ul>*; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_; typename Visitor::result_type = A::C<2ul>*]'
/usr/include/boost/variant/variant.hpp:2401:52:   required from 'typename Visitor::result_type boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::apply_visitor(Visitor&) [with Visitor = const A::C<2ul>; T0_ = A::C<2ul>*; T1 = A::C<1ul>*; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_; typename Visitor::result_type = A::C<2ul>*]'
/usr/include/boost/variant/detail/apply_visitor_unary.hpp:76:43:   required from 'typename Visitor::result_type boost::apply_visitor(const Visitor&, Visitable&) [with Visitor = A::C<2ul>; Visitable = boost::variant<A::C<2ul>*, A::C<1ul>*>; typename Visitor::result_type = A::C<2ul>*]'
34:51:   required from here
/usr/include/boost/variant/variant.hpp:1048:32: error: cannot convert 'A::C<1ul>*' to 'boost::detail::variant::invoke_visitor<const A::C<2ul> >::result_type {aka A::C<2ul>*}' in return
         return visitor_(operand);

如果我从 boost::variant 声明中删除 C *,它可以编译并正常工作。

任何建议都将受到高度赞赏。

【问题讨论】:

    标签: c++ boost stdmap boost-variant


    【解决方案1】:

    所有访问者函数必须遵循基类定义的方案:boost::static_visitor&lt;C&lt;dim&gt; *&gt;

    这意味着operator() 的返回值必须始终为C&lt;dim&gt; * 而不是C&lt;t&gt;* - 请参阅:

    template<size_t dim>
    struct C : boost::static_visitor<C<dim> *> {
    
       template <size_t t>
        C<dim> * operator()(C<t> *s) const {
      //  ^^^ - not t, must be as static_visitor parameter few lines above
          std::cout<<s->x<<std::endl;
          return s; // of course this part will have problems to compile
                    // e.g. pointers to C<2> and C<1> are not convertible
        }
    

    正如我在 return s 右侧放入 cmets - 这不会编译 - 因为编译器无法将 C&lt;1&gt; 转换为 C&lt;2&gt;

    您可能会做的是引入基类 - 如下所示:

    struct CBase {
       int x;
    };
    
    template<size_t dim>
    struct C : CBase, boost::static_visitor<CBase*> {
    
       C() : CBase{dim} {}
    
       template <size_t t>
        CBase* operator()(C<t> *s) const {
          std::cout<<s->x<<std::endl;
          return s; 
        }
    

    【讨论】:

    • 我正在尝试使用 boost::variant 创建模板对象的异构映射。我想了解如何使用 static_visitor 来获取指向对象的指针,因此我在构造函数中使用了它。 t 和 dim 仍然是 size_t 对象,所以应该没有什么不同?但是,它仍然会引发相同的错误。具体来说,以下错误让我感到困惑。 21:22:错误:无法将 'A::C*' 转换为 'A::C*' 在成员函数 'A::C* A::C ::operator()(A::C*) const [with long unsigned int t = 1ul; long unsigned int dim = 2ul]':
    • 查看我在return s; 右边的评论。如果您将其更改为return nullptr;,您将不会有任何错误。但是我敢打赌这不是你想要的......只要记住C&lt;1&gt;C&lt;2&gt; 不是任何相关类型 - 两者都是同一个类模板的实例这一事实不会改变这一事实...... .
    • 但是您可以通过引入基类(如 CBase)来关联 C&lt;1&gt;C&lt;2&gt;,并使用 CBase* 作为运算符的返回值和 boost::static_visitor 的参数 - 这应该可以工作跨度>
    • 行得通!谢谢你。现在,因为我有一个基类指针,所以我必须做一个类型案例来访问 x,比如 static_cast*>(boost::apply_visitor(C(), matrices["Bb"]) )->x。我想在不知道类型的情况下访问成员变量。
    • 因此,我们的想法是使用 ObjA[input] 之类的东西从类外部通过指针 Aasd 或 Bbsd 访问 x 变量(这将是模板大小的特征矩阵)。 “输入”是一个字符串变量,相应地保存“Aa”或“Bb”。由于它将是一个异构映射,我想到了重载“[]”运算符并根据输入字符串访问任一指针。有什么想法或想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多