質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

Q&A

解決済

2回答

1840閲覧

Boost の Operators のようなものを作りたい

cyanhair_neko

総合スコア5

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

0グッド

0クリップ

投稿2019/09/05 13:36

前提・実現したいこと

C++ のライブラリで Boost というのがあるのですが、その中に Operators という一部の演算子オーバーロードから、関連する演算子オーバーロードを自動定義するものがあります。

私は、その Operators と同等の機能を自分でも作れないかと思い、プログラムを組んでいたのですが、想定していた挙動が自力では実現できなかったため、質問させていただきます。

ちなみに実現しようとしていたものは、派生クラスで+=演算子をオーバーロードすると、それに関連する+演算子を派生クラス側でオーバーロードせずに利用できるというものです。

該当のソースコード

Base.h

cpp

1#pragma once 2 3#include <iostream> 4 5template <typename T> 6class CBase 7{ 8public: 9 CBase() {} 10 ~CBase() {} 11 12 T operator+=(const T& a) { 13 return T(); 14 } 15 T operator+(const T& a) { 16 return *this += a; 17 } 18};

Num.h

cpp

1#pragma once 2 3#include "Base.h" 4 5class CNum : public CBase<CNum> 6{ 7public: 8 int num_; 9 CNum(); 10 CNum(int n); 11 ~CNum(); 12 13 CNum& operator+=(const CNum& a); 14 15 // 標準出力で表示する時用 16 int ToInt(); 17};

Num.cpp

cpp

1#include "Num.h" 2 3 4CNum::CNum() 5{ 6} 7 8 9CNum::CNum(int n): 10 num_(n) 11{ 12 13} 14 15 16CNum::~CNum() 17{ 18} 19 20 21CNum& CNum::operator+=(const CNum& a) 22{ 23 this->num_ += a.num_; 24 return *this; 25} 26 27 28int CNum::ToInt() 29{ 30 return num_; 31}

main.cpp

cpp

1#include <iostream> 2#include "Num.h" 3 4int main(void) { 5 6 CNum numA(3), numB(5); 7 CNum numR = numA + numB; 8 9 std::cout << numR.ToInt() << std::endl; 10 11 return 0; 12}

試したこと

一応エラーが出ないようになってはいますが、表示される値が -858993460 と明らかにおかしい値になっています。

T operator+=(const T& a)T operator+(const T& a) の部分がおかしいだろうなということは分かります。それぞれの定義の部分で派生クラスのメソッドを呼び出せたら解決しそうではあるのですが、言語仕様的に可能なのかどうか分かりません。

私がやりたいことはこの方法で可能なのでしょうか。また、実際に Boost の Operators はどのような処理をしているのか知っている人がいましたら、教えて頂けると幸いです。

補足情報(FW/ツールのバージョンなど)

Visual Studio Community 2019

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

すみません、自己解決しましたので方法を書きます。
Base.h 内の演算子オーバーロードを全て friend 関数にして、エラーが出ないようにしたところ、想定していた動作をするようになりました。

以下、該当コードです。

Base.h

cpp

1#pragma once 2 3#include <iostream> 4 5template <typename T> 6class CBase 7{ 8public: 9 CBase() {} 10 ~CBase() {} 11 12 friend T operator+=(const T& a, const T& b) { 13 a += b; 14 return a; 15 } 16 friend T operator+(const T& a, const T& b) { 17 return T(a) += b; 18 } 19};

自己解決はしましたが、もっといいコードの書き方があるなど教えてもらえると幸いです。

投稿2019/09/05 23:29

cyanhair_neko

総合スコア5

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こんにちは。

基本的にはT operator+(const T& a) { return static_cast<T const&>(*this) += a; }
のようにstatic_castすれば良い筈です。
なお、Tに派生先クラスを指定しないとリスクがありますので、フール・プルーフとしてdynamic_castするのも手ですがパフォーマンスは落ちます。そうするくらいなら普通に仮想関数を使って派生先関数を呼び出した方が分かりやすいと思います。

ちなみに、これは CRTP というテクニックです。第19回 CRTPを使ってみよう!で演算子の自動定義も例にとって解説していますので、もし良かったら見てみて下さい。

投稿2019/09/05 14:55

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cyanhair_neko

2019/09/05 23:56 編集

実際に書き換えて実行してみたところ、 エラー C2678 二項演算子 '+=': 型 'const T' の左オペランドを扱う演算子が見つかりません (または変換できません) (新しい動作; ヘルプを参照)。 というエラーが出ました。比較演算子と算術演算子では勝手が違うのでしょうか。 質問していてあれですが、friend 関数にすることで自己解決したのですが、この方法での実装は問題ないのかを、宜しければ教えて頂きたいです。
Chironian

2019/09/06 05:31

あああ、T const&にoperator+=()を定義するとはありえませんね。ついうっかりしてました。 T operator+(const T& a) { return T(static_cast<T const&>(*this))+a; } friend関数で定義するのも「あり」と思います。T型へ暗黙の型変換できるような型Uが存在していた時に、U()+T()を書けるようになるので左右等価なものについては有用な場合もあります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問