【问题标题】:apply boost::fusion::for_each to boost::fusion::vector with mutable function object将 boost::fusion::for_each 应用于带有可变函数对象的 boost::fusion::vector
【发布时间】:2013-02-26 01:01:44
【问题描述】:

我正在尝试使用 boost::fusion::vector。但是,我遇到了一个非常简单的问题。

#include <iostream>
#include <string>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/algorithm.hpp>

using namespace std;

struct A{
    template <class T>
    void operator()(const T& t) {
        x++;
        cout << t << endl;
    }

    int x = 0;
};

int main(){
    A a;
    boost::fusion::vector<int, int, int> tuple{3,4,5};
    boost::fusion::for_each(tuple, a);
}

注意struct Aoperator() 修改了struct A 中的x。 gcc 4.7.2 警告 ...\include\boost\fusion\algorithm\iteration\detail\for_each.hpp:77: 错误:将 'const A' 作为 'void A::operator()( const T&) [with T = int]' 丢弃限定符 [-fpermissive]

有解决办法吗?

【问题讨论】:

    标签: c++ boost boost-fusion


    【解决方案1】:

    一个更简单、更好的方法是使用 fusion::fold:

    #include <iostream>
    
    #include <boost/fusion/algorithm/iteration/fold.hpp>
    #include <boost/fusion/include/fold.hpp>
    
    namespace detail {
      struct A {
        typedef int result_type;
        template<typename T1, typename T2>
        int operator()( const T1& t1, const T2& t2 ) const {
          std::cout << t1 << "," << t2 << std::endl;
          return t1 + 1;
        }
      };
    }
    
    int main() {
      boost::fusion::vector<int, int, int> tuple{3,4,5};
      boost::fusion::fold(tuple, 0, detail::A());
    }
    

    没有任何语法错误,这应该产生:

    0,3
    1,4
    2,5

    【讨论】:

      【解决方案2】:

      好吧,我没有使用 boost::fusion,但是从错误消息和example from docs 来看,for_each 似乎需要 const 对象。 IE。 operator() 也应该是 const 。但是,您将无法改变对象。

      试试这个:

      void operator()(const T& t) const {
          cout << t << endl;
      }
      

      编辑:

      我检查了来源(v. 1.53),声明是for_each(Sequence&amp; seq, F const&amp; f)。所以真的没有办法修改对象本身。我看到的唯一选项是

      要么使用静态变量:static int x;

      或使用指针:

      struct A {
          template <class T>
          void operator()(const T& t) const {
              (*x)++;
              std::cout << t << std::endl;
          }
      
          int* x;
      };
      
      int main()
      {
          A a;
          a.x = new int;
          *(a.x) = 0;
          //...
      

      在这种情况下要小心处理A 实例,因为指针都指向同一个位置。

      【讨论】:

      • 谢谢。实际上,问题都是关于迭代元组并应用可以修改的函数对象。从你的回答来看,我想我不能为此目的使用 boost::fusion。我说的对吗?
      【解决方案3】:

      boost::phoenix::lambda 文档中介绍了解决方案。

      秘诀是在仿函数之外的 lambda 函数中进行各种计算。

      #include <iostream>
      
      #include <boost/fusion/algorithm/iteration/for_each.hpp>
      #include <boost/fusion/include/for_each.hpp>
      
      #include <boost/phoenix/core.hpp>
      #include <boost/phoenix/operator.hpp>
      #include <boost/phoenix/operator/arithmetic.hpp> 
      #include <boost/phoenix/scope/lambda.hpp>
      #include <boost/phoenix/scope/local_variable.hpp>
      #include <boost/phoenix/function.hpp>
      #include <boost/phoenix/fusion.hpp>
      
      namespace detail {
        struct A_impl {
          template<typename T1, typename T2>
          void operator()( const T1& t1, const T2& t2 ) const {
            std::cout << t2 << "," << t1 << std::endl;
          }
        };
        boost::phoenix::function<A_impl> const A = A_impl();
      }
      
      int main() {
        namespace phx = boost::phoenix;
        using boost::phoenix::arg_names::arg1;
        using boost::phoenix::local_names::_a;
        boost::fusion::vector<int, int, int> tuple{3,4,5};
        boost::fusion::for_each(tuple, phx::lambda( _a = 0 )[detail::A(arg1,_a++)]);
      }
      

      没有任何语法错误,这应该会产生:

      0,3
      1,4
      2,5

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多