std :: vectorでの式テンプレート演算子の過負荷問題
-
28-09-2019 - |
質問
現在、式テンプレートを使用する数値ライブラリに取り組んでいます。残念ながら、オペレーターの過負荷に問題が発生しました。以下の削除された例を考えてみましょう。
#include <vector>
namespace test {
class test {};
template<class A, class B>
class testExpr {};
template<class A, class B>
testExpr<A, B>
operator-(A a, B b)
{
return testExpr<A, B>();
}
}
test::test
stuff(std::vector<test::test> &v)
{ return v.back(); }
int main()
{ }
GCC 4.4.3またはClang 2.8とコンパイルすると、次のエラーメッセージが表示されます。
In file included from eir_test.cc:2:
In file included from /usr/include/c++/4.4/vector:64:
/usr/include/c++/4.4/bits/stl_vector.h:696:16: error: indirection requires pointer operand
('testExpr<__gnu_cxx::__normal_iterator<test::test *, std::vector<test::test, std::allocator<test::test> > >, int>' invalid)
{ return *(end() - 1); }
^~~~~~~~~~~~
eir_test.cc:21:12: note: in instantiation of member function 'std::vector<test::test, std::allocator<test::test> >::back' requested here
return v.back();
^
1 error generated.
何らかの理由で、コンパイラーはテスト名空間を検索し、私の一般的なオペレーターを見つけます。私はこのフォームをいくつかの特性魔法と一緒に使用して、オペレーターのために作らなければならなかったバージョンの数を減らしました。さまざまな組み合わせにつながる4つの異なるデータ型(doubleおよびintを含む)を受け入れる必要があります。
すべてのオペレーターのすべての組み合わせを綴ることなく、この作業を行う方法はありますか?
解決
それの訳は end()
タイプの1つの引数があるクラステンプレートの専門化であるタイプを返します test::test *
. 。したがって、いつ operator-
式に適用されます end() - 1
, 、議論に依存するルックアップの外観 また の名前空間で test::test
. 。それはあなたを見つけます operator-
そして、それを繰り返しとansに渡します int
.
すべてのタイプを引数として受け入れないことで修正できます。たとえば、受け入れてみてください (testExpr<A1, B1>, testExpr<A2, B2>)
代わりは。すべての組み合わせを表示してください。おそらく、それらを策定する別の方法を使用してそれらを削減する方法がありますか?
私の意見では、そのように行動する実装は不適合であるべきです(これは本当に嫌だと思います)。やっているから iterator - 1
前の要素に別のイテレーターを生成するように指定されており、そのような狂ったことをしてはいけないと思います。それのための1つの方法は、オペレーターを繰り返しのタイプと整数引数を受け入れる非テンプレートとして宣言することです(これはイテレーターのものです difference_type
) 直接。このようにして、彼らのバージョンは常に推奨されるはずです。
他のヒント
このように変更された場合でも、コードはVC ++バージョン10(Visual Studio 2010 C ++ Expressから)でOKをコンパイルします。
int main()
{
vector<test::test> vec;
test::test instance = stuff(vec);
return 0;
}
これは、コンパイラの制限になる可能性があります。式テンプレートは、コンパイラのテンプレートサポートのストレステストのようなものです。