これを理解できないとは言いたくないのですが、これを理解することはできません。Stack Overflow でググって検索したところ、何も表示されませんでした。
質問の抽象的で、おそらく非常に曖昧な形式は、メンバー関数をインスタンス化するために特性パターンを使用するにはどうすればよいですか? です。 [更新: ここで間違った用語を使用しました。「特性」ではなく「ポリシー」であるべきです。特性は既存のクラスを記述します。ポリシーは合成クラスを規定します。]この疑問は、私が 10 年以上前に書いた一連の多変量関数オプティマイザーを最新化するときに出てきました。
オプティマイザーはすべて、現在の最適なポイントから離れたパラメーター空間を通る直線パスを選択し (「更新」)、その線上でより適切なポイントを見つけ (「ライン検索」)、「完了」をテストすることによって動作します。 "条件、および実行されていない場合は繰り返します。
更新、行検索、およびおそらく完了したテストなどを行うには、さまざまな方法があります。ミックス&マッチ。異なる更新式には、異なる状態変数データが必要です。たとえば、LMQN の更新にはベクトルが必要であり、BFGS の更新には行列が必要です。勾配の評価が安価である場合は、ライン検索でそうする必要があります。そうでない場合は、関数評価のみを使用する必要があります。一部の方法では、他の方法よりも正確なライン検索が必要です。これらはほんの一例です。
元のバージョンでは、仮想関数を使用していくつかの組み合わせをインスタンス化します。一部の特性は、実行時にテストされるモード ビットを設定することによって選択されます。うん。#define で特性を定義し、#ifdef とマクロでメンバー関数を定義するのは簡単です。しかし、それは20年前のことです。奇抜な現代的な方法を理解できないのは私を悩ませています。
変化する特徴が 1 つだけある場合は、奇妙に繰り返されるテンプレート パターンを使用できます。しかし、それを特性の任意の組み合わせに拡張する方法はありません。
などを使ってやってみboost::enable_if
ました。特化した状態情報は簡単でした。this
関数を実行することはできましたが、パラメーターとして -pointerを持つフレンド以外の外部関数に頼るしかありませんでした。関数を友達にする方法、ましてやメンバー関数を作る方法さえ理解できませんでした。コンパイラ (VC++ 2008) は、常に一致しないと不平を言っていました。私は「スフィナエ、馬鹿野郎!」と叫びました。しかし、バカはおそらく私です。
おそらくタグディスパッチが鍵です。私はそのことにあまり深く入っていません。
きっと可能ですよね?もしそうなら、ベストプラクティスは何ですか?
更新:これを説明する別の試みがあります。ユーザーがカスタム オプティマイザーの注文 (マニフェスト) に記入できるようにしたいのですが、中国語のメニューから注文するようなものです - 列 A から 1 つ、列 B から 1 つなど..ウェイター、列 A から (アップデーター) 、コレスキー分解ソースで BFGS を更新します。列 B (line-searchers) から、eta が 0.4、rho が 1e-4 の 3 次補間ライン検索を行います。等...
更新: わかりました。これが私が行った遊びです。しぶしぶ提案するのは、完全に間違ったアプローチだと思うからです。vc++ 2008 では問題なく動作します。
#include <boost/utility.hpp>
#include <boost/type_traits/integral_constant.hpp>
namespace dj {
struct CBFGS {
void bar() {printf("CBFGS::bar %d\n", data);}
CBFGS(): data(1234){}
int data;
};
template<class T>
struct is_CBFGS: boost::false_type{};
template<>
struct is_CBFGS<CBFGS>: boost::true_type{};
struct LMQN {LMQN(): data(54.321){}
void bar() {printf("LMQN::bar %lf\n", data);}
double data;
};
template<class T>
struct is_LMQN: boost::false_type{};
template<>
struct is_LMQN<LMQN> : boost::true_type{};
// "Order form"
struct default_optimizer_traits {
typedef CBFGS update_type; // Selection from column A - updaters
};
template<class traits> class Optimizer;
template<class traits>
void foo(typename boost::enable_if<is_LMQN<typename traits::update_type>,
Optimizer<traits> >::type& self)
{
printf(" LMQN %lf\n", self.data);
}
template<class traits>
void foo(typename boost::enable_if<is_CBFGS<typename traits::update_type>,
Optimizer<traits> >::type& self)
{
printf("CBFGS %d\n", self.data);
}
template<class traits = default_optimizer_traits>
class Optimizer{
friend typename traits::update_type;
//friend void dj::foo<traits>(typename Optimizer<traits> & self); // How?
public:
//void foo(void); // How???
void foo() {
dj::foo<traits>(*this);
}
void bar() {
data.bar();
}
//protected: // How?
typedef typename traits::update_type update_type;
update_type data;
};
} // namespace dj
int main() {
dj::Optimizer<> opt;
opt.foo();
opt.bar();
std::getchar();
return 0;
}