すでに多くの良い答えがありますので、私はあなたの質問のサブセットに対処します。つまり、OOPと機能の特徴は相互に排他的ではないので、私はあなたの質問の前提に無理をします。
C ++ 11を使用する場合、これらの種類の機能プログラミング機能が言語/標準ライブラリに組み込まれ、OOPと(かなり)相乗効果を発揮します。もちろん、上司や同僚がTMPをどれだけ受信できるかはわかりませんが、ポイントは、これらの機能の多くをC ++などの非機能/ OOP言語で何らかの形で取得できることです。
コンパイル時再帰でテンプレートを使用するには、最初の3つのポイントに依存します。
そのテンプレート値は不変(コンパイル時定数)であり、反復は再帰を使用して行われ、分岐は(多かれ少なかれ)オーバーロード解決の形式でパターンマッチングを使用して行われます。
他の点に関しては、を使用するstd::bind
と、std::function
部分的な関数アプリケーションが使用できます。また、関数ポインターは言語に組み込まれています。呼び出し可能オブジェクトは、機能オブジェクト(および部分的な機能アプリケーション)です。呼び出し可能なオブジェクトとは、それらを定義するオブジェクトを意味することに注意してくださいoperator ()
。
遅延評価と純粋な関数は少し難しくなります。純粋な関数の場合、値のみをキャプチャするラムダ関数を使用できますが、これは理想的ではありません。
最後に、部分関数アプリケーションでコンパイル時再帰を使用する例を示します。これはやや不自然な例ですが、上記のポイントのほとんどを示しています。指定されたタプルの値を指定された関数に再帰的にバインドし、(呼び出し可能な)関数オブジェクトを生成します
#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;
}