Şimdiden birçok iyi yanıt var, bu yüzden benimki sorunuzun bir alt kümesini ele alacak; yani, OOP ve fonksiyonel özellikler birbirini dışlamadığından, sorunuzun öncülüne zorlanıyorum.
C ++ 11 kullanıyorsanız, dil / standart kütüphanede yerleşik olan ve OOP ile iyi bir şekilde sinerji yaratan (oldukça) fonksiyonel programlama özelliklerinin birçoğu vardır. Tabii ki, TMP'nin patronunuz veya iş arkadaşlarınız tarafından ne kadar iyi alınacağından emin değilim, ancak mesele şu ki, bu özelliklerin çoğunu C ++ gibi işlevsel olmayan / OOP dillerinde bir şekilde veya başka bir şekilde alabilirsiniz.
Derleme zamanı yinelemeli şablonların kullanılması ilk 3 noktanıza bağlıdır,
- değişmezlik
- özyineleme
- Örüntü Eşleme
Bu şablon değerlerinin değişmez olduğu (derleme zamanı sabitleri), herhangi bir yineleme özyineleme kullanılarak yapılır ve dallanma, aşırı yük çözünürlüğü biçiminde (daha fazla veya daha az) desen eşleştirme kullanılarak yapılır.
Diğer noktaları gelince, kullanma std::bind
ve std::function
size kısmi fonksiyon uygulaması verir ve fonksiyon işaretçileri yerleşik olan dile. Çağrılabilir nesneler işlevsel nesnelerdir (kısmi işlev uygulamasının yanı sıra). Çağrılabilir nesnelerle, onları tanımlayanları kastediyorum operator ()
.
Tembel değerlendirme ve saf işlevler biraz daha zor olurdu; saf işlevler için, yalnızca değere göre yakalanan lambda işlevlerini kullanabilirsiniz, ancak bu ideal değildir.
Son olarak, kısmi işlev uygulamasıyla derleme zamanı özyinelemesinin kullanımına bir örnek. Biraz çelişkili bir örnek, ama yukarıdaki noktaların çoğunu gösteriyor. Belirli bir demet içindeki değerleri belirli bir işleve özyineli olarak bağlar ve (çağrılabilir) bir işlev nesnesi oluşturur
#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;
}