4

奇妙な理由で、この 1 つのコードでテンプレート引数を取得して、互換性のある型に暗黙的にキャストすることができません。

#include <type_traits>

template <typename T, unsigned D>
struct vec;

template <>
struct vec<float, 2> {
    typedef float scalar;
    static constexpr unsigned dimension = 2;

    float x, y;
    float&       operator[] (unsigned i)       { return (&x)[i]; }
    float const& operator[] (unsigned i) const { return (&x)[i]; }
};


template <typename L, typename R>
struct add;

template <typename L, typename R, unsigned D>
struct add<vec<L, D>, vec<R, D>> {
    typedef vec<L, D> left_type;
    typedef vec<R, D> right_type;
    typedef vec<typename std::common_type<L, R>::type, D> return_type;

    add(left_type l, right_type r)
        : left(l),
          right(r)
    {}

    operator return_type() const
    {
        return_type result;
        for (unsigned i = 0; i < D; ++i)
            result[i] = left[i] + right[i];
        return result;
    }

    left_type  left;
    right_type right;
};


template <typename L, typename R, unsigned D>
add<vec<L, D>, vec<R, D>>
operator+(vec<L, D> const& lhs, vec<R, D> const& rhs)
{
    return {lhs, rhs};
}


int main()
{
    vec<float, 2> a, b, c;
    vec<float, 2> result = a + b + c;
}

次の場合に失敗します。

prog.cpp: In function 'int main()':
prog.cpp:55:36: error: no match for 'operator+' in 'operator+ [with L = float, R = float, unsigned int D = 2u](((const vec<float, 2u>&)((const vec<float, 2u>*)(& a))), ((const vec<float, 2u>&)((const vec<float, 2u>*)(& b)))) + c'

したがって、私が正しければ、コンパイラメイン関数のコードを次のように認識します。

  • ((a + b) + c)
  • 計算するa + b
  • の変換演算子を使用してa + bfromの結果をadd<...>to にキャストするvec<float, 2>add<...>
  • 計算する(a + b) + c

しかし、暗黙のキャストは決して行いません。(a + b) の結果を vec に明示的にキャストすると、コードは正常に動作します。

4

2 に答える 2

5

実際の問題を回避し、代わりに推奨事項を作成します。この複雑なボイラープレートをすべてゼロから作成するのではなく、Boostを見てください。Protoは、トリッキーな詳細をすべて処理してくれます。

Proto は、C++ でドメイン固有の組み込み言語を構築するためのフレームワークです。式テンプレートの構築、型チェック、変換、および実行のためのツールを提供します。より具体的には、Proto は以下を提供します。

  • 式ツリー データ構造。
  • 式に追加の動作とメンバーを与えるためのメカニズム。
  • 式からツリーを構築するための演算子のオーバーロード。
  • 式が準拠しなければならない文法を定義するためのユーティリティ。
  • 式テンプレートをすぐに実行するための拡張可能なメカニズム。
  • 式ツリーに適用するツリー変換の拡張可能なセット。

ライブラリ作成者のExpressive C++シリーズの記事も参照してください。これは多かれ少なかれ (優れた) 詳細な Boost.Proto チュートリアルとして機能します。

于 2011-06-22T00:00:38.093 に答える
2

ほとんどの変換は、テンプレートの引数推定では使用されません。

オーバーロードを呼び出すときは、テンプレート引数推定に依存しますoperator+。両方の引数が type である場合にのみ呼び出し可能vec<...>ですが、それを呼び出そうとすると、左側の引数が type になりadd<...>ます。コンパイラは、そのオーバーロードが呼び出されることを本当に意味していることを理解できないため (推測することはできません)、エラーが発生します。

于 2011-06-21T22:30:01.763 に答える