問題タブ [expression-templates]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - オーバーロードの解決が、より具体的なテンプレート関数よりも制約のないテンプレート関数を優先するのはなぜですか?
I have this minimal expression template library with a multiplication, i.e.
and transpose, i.e.
I will introduce some types A
and B
, where the latter is a subclass of the former:
Then, I can call my expression template library as follows (with an overload for printing to std::cout
):
This gives me the output :
So far so good. Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T>
times a variable of type A<T>
for some type T
', as I had in my main
. To this end, I will introduce
上記と同じmain
関数を実行しても、上記と同じ出力が得られます ( unconstrained template
)。transpose<B<double>>
はと比較して完全に異なる型であるため、これは予想されることです。transpose<A<double>>
そのため、オーバーロードの解決では の制約のないテンプレート バージョンが選択されoperator*
ます。
(もちろん、変数定義main
をA
ではなくに変更するとB
、ADL は特殊な関数を呼び出し、出力はcalled: T operator*(const A<T> &one, const A<T> &two)
and になります6
)。
私は最近 SFINAE について学んだので、より具体的な乗算演算子を次のように変更すると、オーバーロードの結果が特殊な関数を選択するようになると予想していました。
SFINAE'doperator*
を使用しても、バージョンを取得できunconstrained template
ます。どうして?より特化したテンプレート関数を呼び出すには、どのような変更を加える必要がありますか?
c++ - 式テンプレートでの部分式のネスト
疎な勾配ベクトル (一次自動微分) を使用して値の操作を処理する式テンプレート ライブラリを作成しています。式が一時的であるかどうかに応じて、参照または値によってサブ式をネストできるようにする方法を見つけようとしています。
値とスパース勾配ベクトルを含むクラス Scalar があります。式テンプレート (Eigen など) を使用して、あまりにも多くの一時Scalar
オブジェクトの構築と割り当てを防ぎます。したがって、 (CRTP)Scalar
から継承するクラスがあります。ScalarBase<Scalar>
タイプのオブジェクト間の二項演算 (+、* など)と、から継承するオブジェクトScalarBase< Left >
をScalarBase< Right >
返す:ScalarBinaryOp<Left, Right,BinaryOp>
ScalarBase< ScalarBinaryOp<Left, Right,BinaryOp> >
ScalarBinaryOp
Left
は、型およびのオペランド オブジェクトへの値または参照を保持する必要がありますRight
。ホルダーのタイプは、テンプレートの特殊化によって定義されRefTypeSelector< Expression >::Type
ます。
現在、これは常に const 参照です。現時点では、テスト ケースでは機能しますが、一時的な部分式への参照を保持することは正しくないか、安全ではないようです。
Scalar
明らかに、まばらな勾配ベクトルを含むオブジェクトがコピーされることも望ましくありません。x
とy
がの場合Scalar
、式は and へのx+y
const 参照を保持する必要がx
ありy
ます。ただし、が からまでf
の関数である場合、への const 参照と の値を保持する必要があります。Scalar
Scalar
x+f(y)
x
f(y)
したがって、部分式が一時的であるかどうかに関する情報を渡したいと思います。これを式の型パラメーターに追加できます。
ScalarBinaryOp< typename Left, typename Right, typename BinaryOp , bool LeftIsTemporary, bool RightIsTemporary >
そしてへRefTypeSelector
:
RefTypeSelector< Expression, ExpressionIsTemporary >::Type
しかし、二項演算子ごとに 4 つのメソッドを定義する必要があります。
私は完全な転送でこれを達成できることを望みます。ただし、ここでこれを達成する方法がわかりません。まず、単純な「ユニバーサル参照」はほとんどすべてに一致するため、使用できません。ユニバーサル参照と SFINAE を組み合わせて特定のパラメーター タイプのみを許可することは可能かもしれないと思いますが、これが正しい方法かどうかはわかりません。ScalarBinaryOp
また、2 つの追加のブール値パラメーターを使用する代わりに、Left と Right が元々左辺値または右辺値参照であったかどうか、およびその情報を取得する方法をパラメーター化する型 Left と Right についての情報をエンコードできるかどうかを知りたいです。
ほとんどが c++11 準拠の gcc 4.8.5 をサポートする必要があります。
update 2019/08/15: 実装
c++ - Variadic テンプレートを使用した式テンプレート演算子
可変個引数テンプレートを使用しadd
て、任意の数の入力パラメーターを受け取り、Expression
(遅延評価される) 1 つのパラメーターを返すfunction を作成できます。特定の index に対して呼び出されると、この式はすべての入力ベクトルのすべてのi
要素を一度に合計します。i
これはすべて非常に素晴らしくきちんとしているように見えますが、実際の operatorをオーバーロードすることは可能ですか。つまり、次のように記述します。
残念ながら、 を使用した 2 番目のコードv1 + v2 + v3
ではコンパイル エラーが発生します。
- VS 2019:
Fatal Error C1001, An internal error has occurred in the compiler.
- GCC 8.3.0:
'Expression<Ts ...> operator+(const Ts& ...)' must have an argument of class or enumerated type
これを機能させる方法はありますか?