ページ 11

テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月20日(水) 21:38
by chibago
C++のgcc(g++)環境におけるテンプレートクラスの挙動に関して2点ほど
疑問に思っているところがございます。(エラーコメントも載せるべきかもしれませんが、
直接関係がないように感じますので記載は遠慮致します。)

以下は、数学のベクトル演算を行うために自作したVectorクラス(STLのものとは関係ありません)
の一つの関数でこれ自体は問題なくコンパイルできます。

template<class T>
Vector<T> Vector<T>::operator+(Vector<T> &other){
return Vector<T>(this->get_x() + other.get_x(),
this->get_y() + other.get_y(),
this->get_z() + other.get_z());
}

演算の相手となるオブジェクトであるotherは変更したくありませんので
以下のようにconstをつけたいのですが、これは通らないようです。

Vector<T> Vector<T>::operator+(const Vector<T> &other){
(これは通りません)

また、戻り値としての結果は速度が気になりますので以下のように、
参照戻しをしたいのですが、これも通りません。

Vector<T>& Vector<T>::operator+(Vector<T> &other){
(これもダメ)

この様な、現象はテンプレートクラス特有のものなのでしょうか。
基本的なことでしたら申し訳ございませんがご指導よろしくお願いします。

ちなみに、コンパイル方法としては
ソース文の最後に
template class Vector<double>;
とつけて倍精度の実装として分割コンパイルをしております.

Re: テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月20日(水) 21:59
by a5ua
コンパイルエラーのメッセージがないので、確かなことはいえませんが、
Vector<T>::get_x()(y, zも)
がconstなメンバ関数でないのが原因だと予想します。

Re: テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月20日(水) 22:27
by chibago
a5ua様、早速のご返事有難うございます。
ご指摘いただいた意図とあっているのか不安ですが、
template<class T>
const T Vector<T>::get_x(){
return this->x;
}
のように、戻り値にconstを付けてみました。(これ自体は通りました。)
エラーとしては以下のような物が出ております。
‘Vector<T> Vector<T>::operator+(const Vector<T>&) [with T = double]’:
Vector.cpp:116:26: instantiated from here
Vector.cpp:19:34: error: passing ‘const Vector<double>’ as ‘this’ argument of ‘const T Vector<T>::get_x() [with T = double]’ discards qualifiers
Vector.cpp:19:34: error: passing ‘const Vector<double>’ as ‘this’ argument of ‘const T Vector<T>::get_y() [with T = double]’ discards qualifiers
Vector.cpp:19:34: error: passing ‘const Vector<double>’ as ‘this’ argument of ‘const T Vector<T>::get_z() [with T = double]’ discards qualifiers

Re: テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月20日(水) 22:42
by chibago
すみません。
T Vector<T>::get_x() const
でしたね。constのいちが間違ってました。
御指摘のとおりに変更した結果
Vector<T>::operator+(const Vector<T>&)
の件は解決しました。
ありがとうございました。

まだ、
Vector<T>& Vector<T>::operator+(const Vector<T>&)
の参照戻しのほうはダメなようです。

Re: テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月20日(水) 23:17
by a5ua
答えになっていないかもしれませんが、
operator◇はoperator◇=を使って実装するのが一般的です。
operator+とoperator+=の実装例を示します。

コード:

template <class T>
class Vector
{
public:
	Vector &operator+=(const Vector &other)
	{
		x += other.x;
		y += other.y;
		z += other.z;
		return *this;
	}
	
	Vector operator+(const Vector &other) const
	{
		Vector result(*this);
		result += other;
		return result;
	}
private:
	T x, y, z;
};

// メンバ関数でなくても作れる
/*
Vector operator+(const Vector &lhs, const Vector &rhs)
{
	Vector result(lhs);
	result += rhs;
	return result;
}
*/

Re: テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月21日(木) 00:04
by たかぎ
chibago さんが書きました:まだ、
Vector<T>& Vector<T>::operator+(const Vector<T>&)
の参照戻しのほうはダメなようです。
これは無理です。
そもそも、返却値はどのオブジェクトの参照を返すというのでしょうか?
operator+関数内の自動オブジェクトの参照を返せないことは理解できますか?
(生存期間が終了していますので)

Re: テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月21日(木) 00:28
by chibago
a5ua様、
実装例有難うございます。
さっそく試してみました。
+=演算子は参照戻し(自分自身の)が可能なようですが、
+演算子はたかぎ様が御指摘のように
スコープが外れると消えてしまう自動オブジェクト
の参照を返せないということでよろしいのですね。

大変勉強になりました。
a5ua様、たかぎ様、改めて有難うございました。

Re: テンプレートクラスを引数とした場合と戻り値の挙動

Posted: 2011年4月21日(木) 00:29
by chibago
解決にチェックを入れるのを忘れていました。