Có rất nhiều câu trả lời hay, vì vậy tôi sẽ giải quyết một tập hợp con câu hỏi của bạn; cụ thể là, tôi rất tin tưởng vào tiền đề của câu hỏi của bạn, vì OOP và các tính năng chức năng không loại trừ lẫn nhau.
Nếu bạn sử dụng C ++ 11, có rất nhiều loại tính năng lập trình chức năng được tích hợp trong thư viện ngôn ngữ / tiêu chuẩn kết hợp tốt (khá) với OOP. Tất nhiên, tôi không chắc chắn ông chủ hoặc đồng nghiệp của bạn sẽ nhận được TMP tốt như thế nào, nhưng vấn đề là bạn có thể nhận được nhiều tính năng này ở dạng này hoặc dạng khác trong các ngôn ngữ không chức năng / OOP, như C ++.
Sử dụng các mẫu với đệ quy thời gian biên dịch dựa trên 3 điểm đầu tiên của bạn,
- Bất biến
- Đệ quy
- Kết hợp mẫu
Trong đó các giá trị mẫu là bất biến (hằng số thời gian biên dịch), bất kỳ phép lặp nào đều được thực hiện bằng cách sử dụng đệ quy và phân nhánh được thực hiện bằng cách sử dụng khớp mẫu (nhiều hơn hoặc ít hơn), dưới dạng phân giải quá tải.
Đối với các điểm khác, việc sử dụng std::bind
và std::function
cung cấp cho bạn ứng dụng chức năng một phần và các con trỏ hàm được tích hợp sẵn trong ngôn ngữ. Các đối tượng có thể gọi là các đối tượng chức năng (cũng như ứng dụng chức năng một phần). Lưu ý rằng bởi các đối tượng có thể gọi được, tôi có nghĩa là những đối tượng xác định chúng operator ()
.
Đánh giá lười biếng và các chức năng thuần túy sẽ khó hơn một chút; đối với các hàm thuần túy, bạn có thể sử dụng các hàm lambda chỉ thu theo giá trị, nhưng điều này không lý tưởng.
Cuối cùng, đây là một ví dụ về sử dụng đệ quy thời gian biên dịch với ứng dụng hàm một phần. Đó là một ví dụ hơi khó hiểu, nhưng nó cho thấy hầu hết các điểm trên. Nó sẽ liên kết đệ quy các giá trị trong một tuple nhất định với một hàm đã cho và tạo một đối tượng hàm (có thể gọi được)
#include <iostream>
#include <functional>
//holds a compile-time index sequence
template<std::size_t ... >
struct index_seq
{};
//builds the index_seq<...> struct with the indices (boils down to compile-time indexing)
template<std::size_t N, std::size_t ... Seq>
struct gen_indices
: gen_indices<N-1, N-1, Seq ... >
{};
template<std::size_t ... Seq>
struct gen_indices<0, Seq ... >
{
typedef index_seq<Seq ... > type;
};
template <typename RType>
struct bind_to_fcn
{
template <class Fcn, class ... Args>
std::function<RType()> fcn_bind(Fcn fcn, std::tuple<Args...> params)
{
return bindFunc(typename gen_indices<sizeof...(Args)>::type(), fcn, params);
}
template<std::size_t ... Seq, class Fcn, class ... Args>
std::function<RType()> bindFunc(index_seq<Seq...>, Fcn fcn, std::tuple<Args...> params)
{
return std::bind(fcn, std::get<Seq>(params) ...);
}
};
//some arbitrary testing function to use
double foo(int x, float y, double z)
{
return x + y + z;
}
int main(void)
{
//some tuple of parameters to use in the function call
std::tuple<int, float, double> t = std::make_tuple(1, 2.04, 0.1);
typedef double(*SumFcn)(int,float,double);
bind_to_fcn<double> binder;
auto other_fcn_obj = binder.fcn_bind<SumFcn>(foo, t);
std::cout << other_fcn_obj() << std::endl;
}