2013-04-30 65 views
2

我想通過使用模板參數來指定do_eval變換的返回類型(到目前爲止double)基於Boost Proto「Unpacking Expressions」示例從here開始構建。模板化簡單Boost Proto C++表達式計算器

爲了簡便起見,我將介紹一個工作,簡化(加只)版本的do_eval

struct do_eval2 : proto::callable 
{ 
    typedef double result_type; 
    template <typename X, typename Y> 
    result_type operator()(proto::tag::plus, X x, Y y) const { return x + y; } 
}; 

我再增加一個模板參數T而不是double

template <typename T> 
struct do_eval2 : proto::callable 
{ 
    typedef T result_type; 
    template <typename X, typename Y> 
    result_type operator()(proto::tag::plus, X x, Y y) const { return x + y; } 
}; 

和修改相關的eval結構爲:

struct eval2 
    : proto::or_< 
     proto::when<proto::terminal<proto::_>, proto::_value> 
    , proto::otherwise<do_eval2<double>(proto::tag_of<proto::_>(), 
             eval2(proto::pack(proto::_))...)> 
    > 
{}; 

但是當我使用它時,如下面的代碼所示,我得到錯誤,從錯誤開始:無法綁定'std :: ostream {aka std :: basic_ostream}'左值爲'std :: basic_ostream & &'我能滿足編譯器嗎?

int main(int argc, char *argv[]) 
{ 
    int one = 1, two = 2; 
    cout << eval2()(phoenix::ref(one)+phoenix::ref(two)) << '\n'; 
    return 0; 
} 

回答

4

正如你可以看到here

Transforms are typically of the form proto::when< Something, R(A0,A1,...) >. The question is whether R represents a function to call or an object to construct, and the answer determines how proto::when<> evaluates the transform. proto::when<> uses the proto::is_callable<> trait to disambiguate between the two. Proto does its best to guess whether a type is callable or not, but it doesn't always get it right. It's best to know the rules Proto uses, so that you know when you need to be more explicit.

For most types R, proto::is_callable checks for inheritance from proto::callable. However, if the type R is a template specialization, Proto assumes that it is not callable even if the template inherits from proto::callable.

的文件提出的解決方案:你要麼換的do_eval<double>每次調用與proto::call,或者你只是專注is_callable了boost ::原命名空間裏,忘記問題。

namespace boost { namespace proto 
{ 
    // Tell Proto that do_eval2<> is callable 
    template<typename T> 
    struct is_callable<do_eval2<T> > 
     : mpl::true_ 
    {}; 
}} 

[編輯:這裏是proto::call選擇:

struct eval2 
    : proto::or_< 
     proto::when<proto::terminal<proto::_>, proto::_value> 
    , proto::otherwise< 
     proto::call<do_eval2<double>(proto::tag_of<proto::_>(), 
            eval2(proto::pack(proto::_))...)>> 
    > 
{}; 
4

見以前的答案。我還想補充一點,另一種解決方案是定義do_eval2這樣的:

template <typename T, typename D = proto::callable> 
struct do_eval2 : proto::callable 
{ 
    typedef T result_type; 
    template <typename X, typename Y> 
    result_type operator()(proto::tag::plus, X x, Y y) const { return x + y; } 
}; 

注意額外的虛擬模板參數。

編輯:另外,在目前正在開發中的Proto的下一個版本中,你不需要知道這件神祕的東西,而且應該只是工作。我將在幾個星期後在C++ Now上談論它。

+3

+1爲答案,很高興看到更多的Boost作者在這個網站上活躍起來! – TemplateRex 2013-05-01 19:10:22

+0

3答案:你們都寵壞了我:) – user2023370 2013-05-01 19:44:40