数値シミュレーション用のプログラムを書いています。私の関数の 1 つがコールバックを受け取ります。関数はテンプレート関数として実装され、コールバックはテンプレート クラスとして実装されるため、コールバックへの呼び出しをインライン化できます。
現在、私の関数は複雑になってきており、明確に定義された自動チェック可能な方法でコールバックのシグネチャを宣言したいと考えています。そこで、C++ Concepts TS に注目しました。
そして、ここに問題があります。std::array
たとえば、を取るファンクタの概念を定義したいと思います
struct sum {
template <class Float, size_t N>
Float operator()(std::array<Float, N> const& arr) {
// return the sum of arr...
}
};
struct avg {
template <class Float, size_t N>
Float operator()(std::array<Float, N> const& arr) {
// return the average of arr...
}
};
注: これは単純化された例です。ファンクターのシグネチャーを変更する (例えばstd::array
、イテレーターのペアに変更する) ことは不可能ではありませんが、好ましくはありません。
sum
以上の共通インターフェースを表す概念をどのように記述するavg
か?
最初に試しました:
template <class F, class Float, size_t N>
concept bool ArrayProcessor = requires (F func, std::array<Float, N> arr) {
func(arr);
};
しかし、これは(私の意見では)醜いコードにつながります。コールバックを使用するテンプレート関数の定義では、その宣言は次のようになります。
template <ArrayProcessor<double, 1> CB, ...>
void simulate(CB const& callback, ...) {
...
}
この<double, 1>
部分は、コンパイルに合格するために必要なダミーです。のテンプレート引数callback.operator()
が内部で変更される可能性があるため、この解決策はほとんど受け入れられませんsimulate
。さまざまなタイプとサイズのstd::array
s を渡すことができます。
2番目に試した:
template <class F>
concept bool ArrayProcessor = requires (F func, auto arr) {
func(arr);
};
このコードは、requires-expression で Constrained-type-specifier を使用する形式が正しくないため、形式が正しくありません (参照: https://groups.google.com/a/isocpp.org/forum/m/#!topic/concepts /_gHn0wJJNGA )。ところで、gcc 6.1.0 はそれに対して内部コンパイル エラーを生成します。
では、問題は次のとおりです。テンプレート クラスをパラメーターとして受け取るファンクターの概念を定義するにはどうすればよいでしょうか (できれば回避策なしで)。
調べてみると、C++ の概念はこのような用途向けに設計されていない可能性があるという印象を受けました。C++ の概念に代わるものへの提案も大歓迎です。
( Concepts Lite を使用してメンバー関数テンプレートを持つ型の概念を指定することに関連している可能性がありますが、重複しているかどうかはわかりません)