c++ - 无法使用 boost::apply_visitor 访问模板对象

标签 c++ boost stdmap boost-variant

我正在学习 boost::variant 并使用 apply_visitor 访问其成员。所以,我写了下面的例子。 我有指向模板化对象的指针作为我的类(class)成员。我想使用 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<1> *,它会编译并正常工作。

如有任何建议,我们将不胜感激。

最佳答案

所有访问者函数必须遵循基类定义的方案:boost::static_visitor<C<dim> *> .

这意味着返回值 operator()必须始终为 C<dim> *不是 C<t>* - 见:

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 右边的评论中所说的那样- 这不会编译 - 因为编译器无法隐藏 C<1>C<2> .

解决这个问题的办法是引入基类——如下所示:

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

关于c++ - 无法使用 boost::apply_visitor 访问模板对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37307252/

相关文章:

c++ - 使用 C/C++ 打开和编辑 SVG 文件

c++ - 当我尝试加载内核模块时,如何修复 C++ 中的 malloc() 错误?

c++ - Boost 程序选项遍历 variables_map

c++ - Boost 无法在 Ubuntu 上使用 CMake 正确链接

c++ - 如何使用变体创建几何体

c++ - 如何从存储在std::map中的std::set中删除元素?

c++ - map , lambda ,remove_if

c++ - 获取 char 数组的一部分

c++ - 从 vector 或 map 中删除共享指针

c++ - Solaris Imakefile 复制文件规则