Sudah ada banyak jawaban bagus, jadi pertanyaan saya akan menjawab sebagian pertanyaan Anda; yaitu, saya mengambil dasar pemikiran pertanyaan Anda, karena OOP dan fitur fungsional tidak saling eksklusif.
Jika Anda menggunakan C ++ 11, ada banyak fitur pemrograman fungsional yang dibangun ke perpustakaan bahasa / standar yang bersinergi (cantik) dengan OOP. Tentu saja, saya tidak yakin seberapa baik TMP akan diterima oleh bos atau rekan kerja Anda, tetapi intinya adalah Anda bisa mendapatkan banyak fitur ini dalam beberapa bentuk dalam bahasa non-fungsional / OOP, seperti C ++.
Menggunakan template dengan waktu rekursi kompilasi bergantung pada 3 poin pertama Anda,
- Kekekalan
- Pengulangan
- Pencocokan Pola
Dalam nilai template yang tidak dapat diubah (konstanta waktu kompilasi), setiap iterasi dilakukan menggunakan rekursi, dan percabangan dilakukan menggunakan (lebih atau kurang) pencocokan pola, dalam bentuk resolusi kelebihan beban.
Adapun poin lainnya, menggunakan std::bind
dan std::function
memberi Anda aplikasi fungsi parsial, dan pointer fungsi adalah bawaan untuk bahasa. Objek yang bisa dipanggil adalah objek fungsional (serta aplikasi fungsi parsial). Perhatikan bahwa dengan objek yang dapat dipanggil, maksud saya objek yang menentukannya operator ()
.
Evaluasi malas dan fungsi murni akan sedikit lebih sulit; untuk fungsi murni, Anda dapat menggunakan fungsi lambda yang hanya menangkap berdasarkan nilai, tetapi ini tidak ideal.
Terakhir, inilah contoh penggunaan rekursi kompilasi-waktu dengan aplikasi fungsi parsial. Ini adalah contoh yang agak dibuat-buat, tetapi menunjukkan sebagian besar poin di atas. Itu akan secara rekursif mengikat nilai-nilai dalam tuple yang diberikan ke fungsi yang diberikan dan menghasilkan objek fungsi (callable)
#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;
}