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

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

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

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

Q&A

解決済

3回答

1365閲覧

結果が通常のメソッドと演算子のオーバーロードとで違ってしまう。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

1クリップ

投稿2020/01/31 21:17

編集2020/01/31 21:26

###質問内容
現在私は可変長引数テンプレートを使い
すべて型が同じ可変長引数から入力された
値をすべて表示するというプログラムを作成しています。

そこで可変長引数を全てstd::coutで出力するprintメソッドと
そのメソッドと全く同じ実装のoperator<<を持つ構造体Aを作成して動かしてみました。
結果はprintメソッドの方は思った通りの動きをしました。
しかしoperator<<の方は可変長引数の最初だけ表示されて残りの引数の内容は
表示されませんでした。

コンパイルはエラーもwaningも吐かずに成功しますが結果がおかしいです。

どうすればoperator<<の方でもすべての値を表示させられるのか教えてください。
どうかよろしくお願いします。

下記がコードです。

c++

1#include <iostream> 2 3template<typename TYPE> 4struct A{ 5 template<typename ...ARGS> 6 void print(ARGS... args){ 7 for(const TYPE& itr:{args...}){ 8 std::cout << itr << ","; 9 } 10 std::cout << std::endl; 11 } 12 13 template<typename ...ARGS> 14 A& operator<<(ARGS... args){ 15 for(const TYPE& itr:{args...}){ 16 std::cout << itr << ","; 17 } 18 std::cout << std::endl; 19 return *this; 20 } 21}; 22 23int main(){ 24 25 A<int> a; 26 a.print(1, 2, 3, 4, 5); 27 a << 1,2,3,4,5; 28 29 return 0; 30}

###結果

terminal

11,2,3,4,5, 21, ←引数の最初の数字しか表示されない。

###補足情報(FW/ツールのバージョンなど)
OS:LinuxMint18.3 Cinammon
コンパイラ:g++ 7.4.0

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

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

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

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

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

guest

回答3

0

ベストアンサー

オペランドの数を変更するような形でのオーバーロードは出来ない旨が仕様に明記されています。

It is not possible to change the precedence, grouping, or number of operands of operators.

結果的に二項演算と解釈可能なようにテンプレートが展開されたときに限っては機能するようですが、三項以上に解釈させることはできません。


二項演算子としてのカンマは左側の評価値を捨てるという意味です。 整数などのプリミティブな型同士の演算の意味を変えることは出来ないので、これをオーバーロードすることも出来ません。


あえて、あくまでもあえて見かけだけそれっぽくするということであればこのように書けなくもないですが、錯覚でそれっぽく見えているというだけなので、他の演算子との組み合わせで簡単に破綻するでしょうね。 基本的には無理と思った方がよいと思います。

cpp

1#include <iostream> 2 3template<typename TYPE> 4struct A{ 5 template<typename ...ARGS> 6 void print(ARGS... args){ 7 for(const TYPE& itr:{args...}){ 8 std::cout << itr << ","; 9 } 10 std::cout << std::endl; 11 } 12 13 template<class T> 14 A& operator<<(T x){ 15 std::cout << x << ","; 16 return *this; 17 } 18 19 template<class T> 20 A& operator,(T x) { 21 std::cout << x << ","; 22 return *this; 23 } 24 25}; 26 27int main(){ 28 A<int> a; 29 a.print(1, 2, 3, 4, 5); 30 a << 1,2,3,4,5; 31 32 return 0; 33}

投稿2020/02/01 02:19

SaitoAtsushi

総合スコア5444

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

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

退会済みユーザー

退会済みユーザー

2020/02/01 03:38

SaitoAtsushiさん 文献のURLとコードを載せていただきありがとうございます。 otnさんとChironianさんと貴方様のご回答を見る限り operatorで複数の右被演算項を 扱おうとすること自体が邪道なのかなと感じました。 ご回答誠にありがとうございました。
guest

0

こんにちは。

演算子オーバーロードで引数の数を元の数から変更することはできなかったはずです。
<<は2項演算子なので、左に1つ右に1つしかパラメータを書けません。
関数呼び出し形式を使って無理やり書いたら、clangは「operator<<は2項演算子なのに6つ指定している」というエラーになりました。

C++

1// 質問文そのままなので略 2 3int main(){ 4 5 A<int> a; 6 a.print(1, 2, 3, 4, 5); 7// a << 1,2,3,4,5; 8 a.operator<<(1,2,3,4,5); 9 10 return 0; 11}

text

1prog.cc:14:8: error: overloaded 'operator<<' must be a binary operator (has 6 parameters) 2 A& operator<<(ARGS... args){ 3 ^ 4prog.cc:28:7: note: in instantiation of function template specialization 'A<int>::operator<<<int, int, int, int, int>' requested here 5 a.operator<<(1,2,3,4,5); 6 ^ 7prog.cc:28:7: error: no matching member function for call to 'operator<<' 8 a.operator<<(1,2,3,4,5); 9 ~~^~~~~~~~~~ 10prog.cc:14:8: note: candidate template ignored: substitution failure [with ARGS = <int, int, int, int, int>] 11 A& operator<<(ARGS... args){ 12 ^ 132 errors generated.

wandbox

投稿2020/02/01 02:09

編集2020/02/01 02:30
Chironian

総合スコア23272

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

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

退会済みユーザー

退会済みユーザー

2020/02/01 03:26

Chironianさん ご回答ありがとうございます。 clangでは動かないんですね... 環境に依存するのなら 使わないほうがいいやり方みたいですね。 勉強になりました。
guest

0

演算子の優先度で、<<より,が低いので、冗長に括弧を付けると、

C++

1( a << 1 ), 2, 3, 4, 5;

ということです。

投稿2020/01/31 22:56

otn

総合スコア84499

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

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

退会済みユーザー

退会済みユーザー

2020/01/31 23:42

otnさん ご回答ありがとうございます。 優先順位の問題なのなら()で優先順位を上げてみようと思い a << (1,2,3,4,5); と書いたら(1,2,3,4,5)の部分がパラメータパックと認識されなかったようで 出力が5のみ表示されてしまいました。 そもそもoperatorで可変長引数テンプレートを取り扱う方法は存在しないのでしょうか。
otn

2020/02/01 00:47

可変長というか、複数の右被演算項を扱う方法は無さそうな気がしますが、よくわかりません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問