1

乗算演算子を TVector3 という名前のテンプレート クラスのフレンドにしようとしています。クラス宣言で宣言する前に、フレンド関数の前方宣言を行うことができると読みましたが、そうしようとしても無駄でした。フレンド関数を宣言する代わりに単純に定義できることはわかっていますが、前方宣言手法で機能させたいと考えています。

特に、私は自分の場合にこのソリューションを実装しようとしていました。David Rodriguez が解決策 (3 番目のバージョン) を提供しているこの投稿も見つかりましたが、何が間違っているのかわかりません。

「 g++ template.cpp tempmain.cpp a 」を使用してコンパイルすると、コンパイラ (g++) は次のエラーを返します。

「ray::TVector3 ray::operator*(float, ray::TVector3 const&)」への未定義の参照

次のコードの場合:

template.h:

#ifndef TVECTOR_H
#define TVECTOR_H

#include <cmath>

namespace ray
{
    //forward declarations
    template <class T> class TVector3;
    template <class T> TVector3<T> operator* (T, const TVector3<T> &);

    template <class T>
    class TVector3 {

        public:
            union {
                struct {
                    T x, y, z;
                };
                T xyz[3];
            };

        //function needed
        friend TVector3<T> operator*<T> (T, const TVector3<T> &);
    };

}

#endif

テンプレート.cpp:

#include "template.h"

using namespace ray;

//friend operator function
template<class T> TVector3<T> operator * (T f, const TVector3<T> &v)
{
    return TVector3<T>(f * v.x, f * v.y, f * v.z);
}

//instantiate template of type float
template class TVector3<float>;

tempmain.cpp:

#include <iostream>
#include "template.h"

int main()
{
    ray::TVector3<float> v1, v2;

    v2.x = 3;
    v1 = 4.0f * v2; //this reports as undefined

    std::cout << v1.x << "\n";

    return 0;
}

それが完全なソースコードです。私は何を間違っていますか?

4

2 に答える 2

4

一般的な経験則として、テンプレートはヘッダーで定義する必要があります。それらを cpp ファイルで定義する場合は、テンプレートを手動でインスタンス化する必要があります。クラス テンプレートに対して実行していますが、operator*テンプレートをインスタンス化していません。

template TVector3<T> operator*<T> (T, const TVector3<T> &);

さらに、テンプレートを使用する代わりにoperator*、クラステンプレート内で宣言および定義することにより、テンプレートを使用しない関数を使用することをお勧めします。

template <class T>
class TVector3 {
//function needed
    friend TVector3<T> operator*(T f, const TVector3<T> & v) {
       return TVector3<T>(f * v.x, f * v.y, f * v.z);
    }
};

これには、無料の関数 (最初の引数で変換が可能) とテンプレート (必要に応じて無料の関数を生成します。つまり、すべての実装を手動で提供する必要はありません) の利点と、限られた可視性 ( ADL を介したルックアップにアクセスできること)

于 2012-08-29T22:23:40.660 に答える
0

operator* を明示的にインスタンス化する必要があり、次のように機能します

using namespace ray;

//friend operator function
template<class T> TVector3<T> ray::operator * (T f, const TVector3<T> &v)
{
    return TVector3<T>(f * v.x, f * v.y, f * v.z);
}

//instantiate template of type float
template class TVector3<float>;
template TVector3<float> ray::operator*<float>( float, TVector3<float> const& );

operator*コンパイラの代わりに書いた場合、ray::operator*意味を知る方法ray::operator*がなく、グローバル名前空間で新しい演算子を宣言していないことに注意してください!

定義することを忘れないでくださいTVector3( T x_, T y_, T z_ ):)

于 2012-08-29T23:24:58.820 に答える