3

これは本当に最小限の例です。Boost.Unitsを次のように使用しています。

#define REAL double
...
using namespace boost::units;
quantity<si::velocity, REAL> v;

それから時々私は次のようなものが必要です

quantity<si::velocity, REAL> v_halved;
v_halved = 0.5 * v;

0.5コンパイラはとして扱うので、これは問題なく動作しdoubleます。しかし、REAL何かが違うとコンパイルエラーが発生します。たとえば、定義をコンパイルエラーに変更すると、次のREALようにlong doubleなります。

error: no match for ‘operator*’ in ‘5.0e-1 * v’
/usr/include/boost/units/detail/one.hpp:58: note: candidates are: boost::units::one boost::units::operator*(const boost::units::one&, const boost::units::one&)

Boost.Units のドキュメント調べる と、次のようにオーバーロードされていることがわかりました。operator*

// runtime scalar times quantity 
template<typename Unit, typename X> 
  multiply_typeof_helper< X, quantity< Unit, X > >::type 
  operator*(const X & lhs, const quantity< Unit, X > & rhs);

doubleスカラーと数量の内部型が同じでなければならないことは定義から明らかですが、変換が暗黙的に実行できる場合 ( from からへのように) コンパイラが自動的に型を変換することを期待しますlong double。ただし、自動型変換は のような他の単純な関数でも確実に機能するため、何かが欠けている可能性があると思いますlong double f(long double const & ld)

私の問題は、私がv_halved = 0.5 * v非常に多くの式を使用しており、私のプロジェクトがすでにかなり大きくなっていることです。これが問題であることを認識しなければならないことを定義REALしなければならないのは今だけです。long doubleそれで、私はこれに対する回避策/解決策について疑問に思っていました.それがstatic_cast<REAL>(0.5)解決策になることは承知していますが、コンパイラーがスカラーを適切な型に自動的に変換できないことについて何かが欠けていると感じています.

よろしくお願いします!

4

1 に答える 1

3

テンプレート関数は、非テンプレート関数とは異なります。コンパイラは、暗黙的なキャスト/昇格を考慮せずにテンプレート関数を選択することを決定します。完全一致を探すだけです。

これは、C++ がこの領域でどのように機能するかです。

完全一致を取得するには、そのようなoperator *定義が必要です (この追加のテンプレート パラメータ Y に注意してください)。

template<typename Unit, typename X, typename Y> 
  typename multiply_typeof_helper< X, quantity< Unit, X > >::type 
  inline operator*(const Y & lhs, const quantity< Unit, X > & rhs)
{
    return static_cast<X>(lhs) * rhs;
}

のブースト定義に干渉するのではないかと心配しています*quantityこれで遊ぶことができます-ブーストからほぼ完全に派生する独自のものを定義するように-しかし、私が提案した別の方法で乗算を定義します。

どちらが使いやすいかを決めるだけです

  • 静的キャストを実行します(または、単に追加してL- 0.5Llong double を定数にします)
  • または、テンプレートとの組み合わせを行います。
于 2012-10-15T20:25:48.953 に答える