2010-03-19 26 views
5

tại thời điểm này tôi thực sự quan tâm đến các mẫu biểu thức và muốn mã hóa thư viện để viết và phân biệt các hàm toán học với cú pháp kiểu lambda. Tại thời điểm này, tôi có thể viết (_x * _x)(2); và nhận được kết quả chính xác 4. Nhưng tôi thực sự muốn làm một cái gì đó như MathFunction f = _x * _x; f(2);, nhưng tôi không có bất kỳ ý tưởng về cách đối phó với các mẫu biểu hiện đệ quy ở phía bên phải . Có thể đạt được điều này mà không sử dụng 'auto'-Keyword thay vì MathFunction hoặc phải làm cho toán tử() ảo không?Lưu trữ các mẫu biểu mẫu functors

Cảm ơn sự giúp đỡ của bạn!

Trả lời

0

Vì tôi là người mới đến trang web này, tôi đã tìm thấy this cho đến khi tôi gửi câu hỏi này. Cảm ơn câu trả lời của bạn, nhưng đây là những gì tôi đã thực sự tìm kiếm.

1

Vâng, Boost đã hỗ trợ chức năng này, vì vậy bạn có thể muốn xem cách họ đã thực hiện.

Các liên kết sau là thực sự hữu ích khi tôi đang học:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Expression-template
http://www.angelikalanger.com/Articles/Cuj/ExpressionTemplates/ExpressionTemplates.htm http://www.flipcode.com/archives/Faster_Vector_Math_Using_Templates.shtml

Các liên kết thứ hai là yêu thích cá nhân của tôi!

Tất cả tốt nhất.

+1

Cảm ơn câu trả lời này và các liên kết! Tôi đã quét tài liệu Boost.Lambda cho một giải pháp cho vấn đề của mình, nhưng tôi đã không tìm thấy một dòng nơi các hàm lambda đó thực sự được "lưu trữ", chúng luôn được sử dụng nội tuyến. Hiện tại, tôi sử dụng phương pháp "C++ Templates - Hướng dẫn xác định" để hiển thị mẫu. – fhenneke

+1

Ngoại lệ không bắt buộc, tôi đã đề xuất bạn xem mã nguồn. Bạn đã nhìn chưa? – batbrat

3

.

template<class T, class R> 
struct MathFuncBase 
{ 
    virtual R operator()(const T & v) = 0; 
    virtual ~MathFuncBase() {} 
}; 

tempate<class T, class R, class Func> 
struct MathFunc : MathFuncBase<T, R> 
{ 
    MathFunc(Func func) : func(func) {} 
    virtual R operator()(const T & v) { 
     return func(v);   
    } 
private: 
    Func func; 
}; 

tempate<class T, class R, class Func> 
boost::shared_ptr<MathFuncBase<T, R> > GetMathFunc(Func func) { 
    return boost::shared_ptr<MathFuncBase<T, R> >(new MathFunc<T, R, Func> (func)); 
} 

int main() { 
    boost::shared_ptr<MathFuncBase<int, int> > f = GetMathFunc<int,int> (_x * _x); 
    return (*f)(2); 
} 
+0

'MathFuncBase' destructor phải là ảo cho trường hợp sử dụng của bạn. Khác khi 'shared_ptr' đi ra khỏi phạm vi nó sẽ có hành vi không xác định. –

+0

destructor ảo là tốt. Nhưng trong trường hợp của 'shared_ptr' nó không cần thiết. Kiểm tra điều này. –

+0

Tôi đoán bạn có nghĩa là cung cấp một tham chiếu bị mất ở đâu đó ... dù sao, với 'shared_ptr' bạn có thể cung cấp deleter của riêng mình làm tham số cho hàm tạo, nhưng trong khối mã ở trên bạn không cung cấp nó.Nếu bạn không cung cấp đối số thứ hai cho hàm tạo 'shared_ptr', khi hủy, nó sẽ gọi' delete' trên kiểu con trỏ được lưu trữ ('MathFuncBase'). Trong trường hợp đặc biệt này, UB hầu như không có hiệu ứng (xấu) (không phải cơ sở cũng như các đối tượng có nguồn gốc chứa bất kỳ thành viên nào hoặc thực hiện bất kỳ khởi tạo hoặc hủy diệt nào) nhưng nó vẫn là UB. –

0

Tôi nghi ngờ rằng điều này có thể không có chức năng ảo. Bạn cần phải loại xóa vì bạn không thể sử dụng auto và tương tự. Nhưng sau đó sau đó trong phạm vi đó kể từ khi bạn đang gọi một chức năng trên đối tượng loại erasured bạn cần hỗ trợ thời gian chạy để gọi một hàm trên đối tượng lớp dẫn xuất.

Tôi nghi ngờ không có auto bạn không thể làm điều đó.

1

Thực ra tôi không nghĩ rằng có một cách đơn giản để lưu trữ chúng. Nếu tôi muốn tạo một đối tượng tên là biểu hiện tăng :: lambda, tôi sẽ gán kết quả đến, nói, int và sau đó sao chép tên của các loại cần thiết từ thông báo lỗi của trình biên dịch:

#include <boost/lambda/lambda.hpp> 

int main() 
{ 
    using namespace boost::lambda; 
    //int x = _1 + _2; 
    boost::lambda::lambda_functor<boost::lambda::lambda_functor_base< 
    boost::lambda::arithmetic_action<boost::lambda::plus_action>, 
    boost::tuples::tuple<boost::lambda::lambda_functor<boost::lambda::placeholder<1> >, 
    boost::lambda::lambda_functor<boost::lambda::placeholder<2> >, 
    boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, 
    boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, 
    boost::tuples::null_type, boost::tuples::null_type> > > x = _1 + _2; 
} 

Trong cuộc sống thực bạn sẽ có nhiều khả năng để lưu trữ chúng trong một loại, mà loại xóa, như boost::function.

#include <boost/lambda/lambda.hpp> 
#include <boost/function.hpp> 
int main() 
{ 
    using namespace boost::lambda; 
    boost::function<int(int, int)> x = _1 + _2; 
    return x(-1, 1); 
} 
Các vấn đề liên quan