Bạn cũng có thể tách chức năng 'lấy giây ghép nối' khỏi 'tính toán MULT * VAL' và 'thêm thứ gì đó vào bộ tích lũy'.
Mặc dù bạn không cần tăng cường để làm điều này, họ đã tạo ra rất nhiều khung công tác lập trình 'chức năng'. Nếu bạn không thể sử dụng tăng, bạn cần một số mẫu ma thuật của riêng bạn. Tuy nhiên, không phải quá phức tạp.
#include <map>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>
Bây giờ tôi xét thấy tốt hơn để đưa các nhân bên lớp.
struct SMyStruct
{
int MULT;
int VAL;
long f() const { return MULT*VAL; }
};
Tạo một functor chung cho 'mất thứ hai của cặp':
// a 'take-second' functor
template< typename at_pair >
struct to_second_t : public std::unary_function< at_pair, typename at_pair::second_type > {
const typename at_pair::second_type& operator()(const at_pair & p) const {
return p.second;
}
};
này trông khôn lanh, nhưng chỉ đơn thuần là một cách chung chung nói: 'đầu tiên làm điều này, sau đó làm điều đó với kết quả ':
// compose two functors (simplified)
template< typename at_F, typename at_G >
struct compose_t : public std::unary_function< typename at_F::argument_type, typename at_G::result_type >{
at_F f;
at_G g;
compose_t(at_F& f, at_G& g): f(f), g(g) {}
typename at_G::result_type operator()(const typename at_F::argument_type& v) const {
return g(f(v));
}
};
template< typename at_F, typename at_G >
compose_t<at_F, at_G> compose(at_F& f, at_G& g) { return compose_t<at_F,at_G>(f, g); }
// compose two functors (a unary one, and a binary one)
//
template< typename at_F, typename at_G >
struct compose2_t : public std::binary_function< typename at_F::first_argument_type, typename at_G::argument_type, typename at_G::result_type >{
at_F f;
at_G g;
compose2_t(at_F& f, at_G& g): f(f), g(g) {}
typename at_G::result_type operator()(const typename at_F::first_argument_type& a1, const typename at_G::argument_type& v) const {
return f(a1, g(v));
}
};
template< typename at_F, typename at_G >
compose2_t<at_F, at_G> compose2(at_F& f, at_G& g) { return compose2_t<at_F,at_G>(f, g); }
Và cuối cùng, đặt nó tất cả trong thực tế:
int main()
{
typedef std::map<int, SMyStruct > tMap;
tMap m;
SMyStruct s = {1,2};
m[1].VAL = 1; m[1].MULT = 3;
m[2].VAL = 2; m[2].MULT = 10;
m[3].VAL = 3; m[3].MULT = 2;
// mind, this is not LISP (yet)
long total = std::accumulate(m.begin(), m.end(), 0,
compose2(
std::plus<int>(),
compose(
to_second_t<tMap::value_type>(),
std::mem_fun_ref(&SMyStruct::f)))
);
std::cout << "total: " << total <<std::endl;
return 0;
}
Aw, bb đánh tôi với câu trả lời, vì vậy tôi sẽ có một chút cảm giác thay thế: Bạn biết dấu gạch dưới hàng đầu nói chung là một ý tưởng tồi, phải không? (dành riêng cho việc thực hiện trong hầu hết các trường hợp) Và tiền tố S trên một cấu trúc là tiếng ồn hoàn toàn vô nghĩa. :) – jalf
argh, ok ... Vâng, chúng tôi luôn luôn tiền tố cấu trúc với S và các lớp học với C; nhiệm vụ tiêu chuẩn mã hóa của chúng tôi. Tức là "_", tôi đồng ý nhưng vì nó không phải là một phần của bất cứ điều gì, tôi để nó như vậy. Tôi thường sử dụng m_ cho các thành viên g_ cho globals và s_ cho tĩnh. Cảm ơn đã chỉ ra điều đó. –
Các _ * có thể * về mặt kỹ thuật là ok. Các quy tắc là một cái gì đó như "Double hàng đầu _ OR hàng đầu _ theo sau là lá thư vốn được dành riêng cho việc thực hiện. Dẫn đầu _ theo sau là bất cứ điều gì khác được dành riêng trong không gian tên toàn cầu".Dễ nhất để tránh hoàn toàn dẫn đầu _) – jalf