【问题标题】:Problems adapting member functions in Phoenix在 Phoenix 中调整成员函数的问题
【发布时间】:2014-09-10 16:19:41
【问题描述】:

我在 Spirit 中一直使用BOOST_PHOENIX_ADAPT_FUNCTION。出于同样的原因,我希望能够调整成员函数。但是,如果我执行以下操作会出现编译错误:

struct A { int foo(int i) { return 5*i; }};

BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, &A::foo, 2)

有没有一种简单的方法来调整成员函数?请注意,我不能只将绑定表达式存储在 auto 中,因为我在 VC2008 上。为什么它不像 bindfunction 那样工作?

谢谢,

迈克

【问题讨论】:

    标签: c++ boost boost-phoenix


    【解决方案1】:

    BOOST_PHOENIX_ADAPT_FUNCTION(RETURN,LAZY_NAME,FUNC,N) 非常简单。它只是创建一个带有模板化operator() 的函子,它返回RETURN 并具有N 模板参数。在它的主体中,它只是调用FUNC(PARAMETERS...)。但是&A::foo 不能直接调用,所以你的错误就会发生。您可以使用:

    BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
    

    Running on Coliru

    #include <iostream>
    #include <boost/phoenix.hpp>
    #include <boost/phoenix/function.hpp>
    #include <boost/mem_fn.hpp>
    
    struct A {
        A(int f) : f_(f) {}
    
        int foo(int i) {
            return f_*i;
        }
      private: 
        int f_;
    };
    
    BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
    
    int main() {
        using namespace boost::phoenix;
        using namespace boost::phoenix::arg_names;
    
        A instance(5);
        std::cout << AFoo(arg1,arg2)(&instance, 2) << std::endl;
    }
    

    【讨论】:

    • 我知道这个答案已经晚了,但它可能会帮助一些未来的访客。
    【解决方案2】:

    从最简单的开始:

    为什么它不像在绑定和函数中那样工作?

    因为宏是为函数设计的,而不是为成员函数设计的。指向成员函数的指针与函数指针非常不同,所以这就是路的尽头。


    在您的示例中,A::foo 实际上不需要是 实例方法(非静态成员函数),因此只需添加 static(和隐式参数)即可完成:

    struct A {
        static int foo(int i) {
            return 5*i;
        }
    };
    
    BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, A::foo, 1)
    

    不过,让我们假设您确实想要拥有非静态成员函数。为此,让我们为A 类型添加一点状态:

    struct A {
        A(int f) : f_(f) {}
        int foo(int i) { return f_*i; }
      private: 
        int f_;
    };
    

    Phoenix 提供以下方法来创建调用成员函数的惰性 Actor:

    1. 使用-&gt;* 运算符。这会导致语法有点晦涩:

      A instance(9);
      
      int direct    = (arg1->*&A::foo)(arg2)
                          (&instance, 7); // direct == 63
      
    2. 或者,您可以使用 bind 表达式(注意:boost::phoenix::bind 此处!),这可能正是您要查找的内容:

      int with_bind = bind(&A::foo, arg1, arg2)
                          (&instance, 7);
      

    现在,当然,您可能希望将惰性函子分配给一个变量。这方面我只能推荐BOOST_AUTO

    BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
    return afoo(&instance, 2);
    

    这就像一个魅力。

    完整的 C++03 示例

    Live on Coliru

    struct A {
        A(int f) : f_(f) {}
    
        int foo(int i) {
            return f_*i;
        }
      private: 
        int f_;
    };
    
    #include <boost/phoenix.hpp>
    #include <boost/phoenix/function.hpp>
    #include <cassert>
    
    int main() {
        using namespace boost::phoenix;
        using namespace boost::phoenix::arg_names;
    
        A instance(9);
    
        int direct    = (arg1->*&A::foo)(arg2)
                            (&instance, 7);
    
        int with_bind = bind(&A::foo, arg1, arg2)
                            (&instance, 7);
    
        assert(direct == with_bind);
    
        BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
    
        return afoo(&instance, 2);
    }
    

    【讨论】:

    • 感谢您的回答。不幸的是,这正是我所害怕的。在我的程序 VS2008 上似乎对我有用的唯一一个是绑定解决方案,这是我一直在使用的并希望有更好的东西(由于嵌套模板,有一些不稳定的上下文)。哦,好吧,至少知道是件好事。
    猜你喜欢
    • 2017-12-25
    • 2020-03-16
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 2021-03-30
    相关资源
    最近更新 更多