C++相談室 part157

■ このスレッドは過去ログ倉庫に格納されています
2021/08/09(月) 10:57:31.60ID:JaaB5Egp
前スレ
C++相談室 part156
https://mevius.5ch.net/test/read.cgi/tech/1621389313/
2021/10/20(水) 07:45:51.66ID:GCto648C
>>763
x,y,zのデストラクタならcatchに飛んだ時に呼ばれることは保証されてるけど…?
例えばyのコンストラクタで例外飛んでもxは~Bar()呼んでzは呼ばないくらいコンパイラがやってくれるけど…?
そういうの忘れずやってくれるのがコンパイラだから任せようぜっていうのがRAIIなんだけど…?

まさかこんな事も知らずに例外安全がどうのと偉そうに論じてたの?嘘だろ?
2021/10/20(水) 07:47:08.92ID:GCto648C
>>765
お前はもう喋るなド初心者
2021/10/20(水) 07:47:29.23ID:0k8Pnquo
>>766
ま た 文 盲 か
>(x, y, zの解放が保証される、
と書いてあるわけだが?
しかしだからといっても普通の人はtryブロック内をチェックするだろ、という主張
2021/10/20(水) 07:55:59.64ID:GCto648C
>>768
初心者はおとなしく教科書の質問だけしてろよ
何かを知っているふりをするのをやめろ
2021/10/20(水) 08:05:08.97ID:0k8Pnquo
>>769
質問ですが例外安全の教科書として藻前は何を読んだことがあるのでぃすか?
2021/10/20(水) 08:13:47.58ID:kO478Zp/
> 例外安全主義者にかかってはそんなことはお構いなしである。とにかく安全と言い張る
どこの主張を言ってるのか知らんけどどう見てもお前の方が「文盲」なわけだがw
2021/10/20(水) 08:27:40.98ID:DhnN+uGO
>>763
RAII を使わず明示的な catch でリソース解放しているコードを見て、一般的な C++ プログラマは「危険」だと見るのでは?
その例だと「fgets()とかのコード」内の return などで fp がリークする可能性があるわけで。
2021/10/20(水) 08:31:29.32ID:xpWbVnlK
誰が「例外安全なら大丈夫」と言っているの?レス番は?
774デフォルトの名無しさん
垢版 |
2021/10/20(水) 09:12:35.95ID:OEiI06HQ
Kuso.KENTA.
2021/10/20(水) 09:21:20.26ID:glY3n63N
いつになっても
do {
} while(0);
でbreakをgoto代わりに使うしかないのか
2021/10/20(水) 09:23:08.99ID:NMVwWGr0
>>763
めまいがするほどのひでえコード
やめてくれバカがうつる
777デフォルトの名無しさん
垢版 |
2021/10/20(水) 09:35:49.31ID:OEiI06HQ
>>743
観ようとしなければ何も観えない
そんな簡単なことにも気付けない
778デフォルトの名無しさん
垢版 |
2021/10/20(水) 09:39:48.17ID:OEiI06HQ
>>757
2GB以上じゃなくて良いけど
そこそこの大きさのファイルで
書き込んでcloseしてる途中に
電源OFFとかになったら例外どころじゃないんだが
最近のOSはちゃんとコンデンサ放電仕切るまでの間に書き込み終了するんだろうか
779デフォルトの名無しさん
垢版 |
2021/10/20(水) 09:44:46.84ID:OEiI06HQ
>>760
サンフランシスコ地震で高速道路崩落←直後に「日本では起こり得ない」と言われた
インドネシアの津波で街が吹っ飛ぶ←直後に「日本では起こり得ない」と言われた
チェルノブイリで原発爆発←直後に「日本では起こり得ない」と言われた
武漢でコロナ感染者急増でパニック&パンデミック←直後に「日本では起こり得ない」と言われた
いつも否定したがる人はいるしそれを信じたがるひともいる
2021/10/20(水) 11:10:43.38ID:NMVwWGr0
>>778
UPSもアレスタも知らないど素人w
2021/10/20(水) 11:15:17.23ID:glY3n63N
ファイル編集中、Ctrl+Sを押下して保存しようとした瞬間に停電になったことがある
再起動後、ファイルは存在しているのに中身は\0で埋められていたよ
2021/10/20(水) 11:16:33.48ID:PaxGKk4c
>>778
・UPSぐらい付けろよ
・障害が心配なら多重化しとけ
って話で例外安全とはレイヤーの違う話
2021/10/20(水) 11:28:28.97ID:EqJEar1P
>>770
古典だけどExceptionalC++あたりから読み始めるのがいいよ
準拠規格が古いから所々アレだけど大きな考え方を学ぶには十分だろう
感想聞かせてね
2021/10/20(水) 11:41:33.49ID:Px+syONf
いつもの
2021/10/20(水) 11:43:42.24ID:BFKUlxpT
786以降C++なコードもC++なURLも載せないやつは発言禁止な
2021/10/20(水) 12:28:18.88ID:vkb7a42p
>>763
try内のコードが例外出さない限りcloseされない
2021/10/20(水) 12:55:58.99ID:Px+syONf
確かにそうだ
すっかりfinallyのつもりで読んでた
やはりRAIIは正義
2021/10/20(水) 13:11:06.68ID:NMVwWGr0
いーやfreadで2G超のファイルはvsでも完全にあつかえる不都合はない
と、自信を持って断言できないゴミが
URL乞食でドヤってるのバカすぎ
2021/10/20(水) 13:28:11.75ID:vkb7a42p
C++にもfinally欲しい
790デフォルトの名無しさん
垢版 |
2021/10/20(水) 13:30:01.90ID:OEiI06HQ
fseek()/ftell()が32bit用でfseeki64()/ftelli64()の方を使ってないというオチか
2021/10/20(水) 13:36:27.87ID:glY3n63N
自信をもって断言したところで、モリカケ・桜を見る会と同じことになるだけだよ
アベノセイダーズは不具合を見つけてくるまで決して許さない
2021/10/20(水) 13:39:14.76ID:glY3n63N
>>789
コストラクタでラムダ式をメンバ変数に受け取りデストラクタでそのラムダ式のメンバ変数を実行するクラステンプレートを自作すれば問題解決
2021/10/20(水) 13:41:35.24ID:NsIIvpqv
fseekの引数はなぜああしたんだろうね
2021/10/20(水) 13:46:56.17ID:glY3n63N
宇宙人がいないことを証明するための労力たるや
2021/10/20(水) 13:50:04.27ID:NMVwWGr0
不都合があるという主張であろうと
不都合がないという主張であろうと
自分でコード書けないゴミは引っ込んでろ
2021/10/20(水) 13:53:43.95ID:glY3n63N
>>795
そのとおりだな、まずお前が引っ込め
2021/10/20(水) 14:13:30.21ID:glY3n63N
再帰呼び出し

我々の宇宙は高度な文明を持つ知的生命体の実験により作られたものであると推測するハーバード大学の科学者 : カラパイア
https://karapaia.com/archives/52306877.html
2021/10/20(水) 14:38:01.57ID:NMVwWGr0
>>796
おいURL乞食、おまえに言ってんだよ、おまえに
俺はftellで例示するコード出してんだよ
同類呼ばわりすんな穢らわしい
2021/10/20(水) 14:47:18.86ID:BFKUlxpT
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdio>
#include <algorithm>
int main()
{
const char path[] = { "hoge.dat" };
std::vector<char> buffer(1024 * 1024); // 1MB
std::ofstream f(path, std::ios::binary);
for (int gb = 0; gb < 5; ++gb) {
std::fill(buffer.begin(), buffer.end(), static_cast<char>(gb));
for (int i = 0; i < 1024; ++i) f.write(buffer.data(), buffer.size());
}
f.close();
#pragma warning(suppress : 4996)
std::FILE* fp = std::fopen(path, "rb");
for (int i = 0; i < 5 * 1024; ++i) {
if (std::fread(buffer.data(), sizeof(buffer[0]), buffer.size(), fp) < buffer.size()) return 1;
for (auto ch : buffer) if (ch != static_cast<char>(i / 1024)) return 2;
}
std::fclose(fp);
std::cout << static_cast<int>(buffer[buffer.size() - 1]) << std::endl;
return 0;
}
とりあえずVC++2019でx86(32bit)ビルドして実行したら終了コード0の出力4だったのでfread 4GBは超えられてる模様
2021/10/20(水) 15:12:34.13ID:glY3n63N
>>799
それは、おま環にすぎないので不具合がないことの証明にはならない
不具合を見つけるのがお前の責務だ
赤木さんのように自○したくなるまで頑張って探せ
2021/10/20(水) 15:18:25.38ID:BFKUlxpT
今日は2つのIDで頑張ってるみたいだね
2021/10/20(水) 15:29:22.63ID:NMVwWGr0
プログラム技術板の正規メンバに
クソ以外の乞食が何か寝言ぬかしとんな
2021/10/20(水) 15:34:29.03ID:glY3n63N
お前らの家の冷蔵庫にエルビス・プレスリーがいないからといって、この世にエルビス・プレスリーがいないことの証明にはならないんだよ
血を吐くまで探せ
2021/10/20(水) 15:55:06.91ID:4r95dvH8
不具合あるのを証明したほうがてっとりばやい
2021/10/20(水) 16:02:32.88ID:glY3n63N
あぁ?わかって言ってんのか?
泥棒の証拠を泥棒に探させるのがアベガー品質だぞ
2021/10/20(水) 16:09:49.79ID:Px+syONf
元々>>637がC++でもfgetsを使う俺は天才などとのたもうて
>>687がFILE*を使うなら例外安全をどう保証するのという話だったのが、
当の>>637>>691でfread/fgets自体が例外を投げる可能性(?)という謎の問題を考え始め
>>710が根拠不明の2GB制限の話を持ち出し

問題があると考えるひとは存在しない2個の問題を同時に考えて混乱し
まあまあ分かってる人はRAIIすればいいじゃん(ってかfstreamでいいじゃん)で話が終わっている

まとめるとこんなところか?
807デフォルトの名無しさん
垢版 |
2021/10/20(水) 16:17:28.71ID:glY3n63N
挙証責任をガン無視できる文部科学省元事務次官前川喜平こそ最強
座右の銘は面従腹背、ライフワークは貧困調査
2021/10/20(水) 16:39:46.06ID:NMVwWGr0
キチガイ極左は内ゲバで共食いしとれ
2021/10/21(木) 00:40:30.45ID:ObBh/rk9
>>806
俺はcの標準ライブラリ使うならosの関数使えって言ってた人でアンカの中には登場しない人だけど
「根拠不明の2GB制限」についてはlarge file問題というのが昔あった
https://en.wikipedia.org/wiki/Large-file_support
LinuxなどUnix系が64bit環境にほぼ移行した現在その問題はレアケースだとは思うけど
32bitアプリが割と残っているWindowsだと実際のところどうなのか分からない
でもfreadくらいは出来そうだと考えわざわざコード書いただけ(>>799)
ちなみにLinuxでもdebian系のantiX 19.4 32bit環境では#define _FILE_OFFSET_BITS 64がないとfopenがNULLを返していた
2021/10/21(木) 00:51:53.61ID:l0SlZ35R
話の肝は「私が間違ってました。ごめんなさい」と素直に言えるかどうかなわけで
小室文書みたいな屁理屈の羅列はいらねンだわ
2021/10/21(木) 01:06:38.58ID:5bux1k1I
>>807
NHK は メード イン ジャパン とか オーダー メード とか表記するのに
メイド 喫茶は なぜ メイド 表記なのですか?
2021/10/21(木) 01:19:29.04ID:ObBh/rk9
ちなみに>>809の「cの標準ライブラリ使うならosの関数」という意味で以前実験した結果も貼っとく
read, fread, std::ifstream::readの比較
https://ideone.com/H2jc7B
systemdのユーザーごとのRAMディスクを使っているのでそれがある環境でだけ動作する
ubuntu 20.04 64bit環境で実行した結果だと↓
$ g++ -O2 test.cpp -o test
$ ./test
227
267
225
$
2021/10/21(木) 03:46:14.13ID:Y6x8PTxQ
>>811
前者がmadeで後者がmaidだからじゃね?
2021/10/21(木) 07:45:14.90ID:5PpYpVBN
以前はメードだったと思うけどね
815デフォルトの名無しさん
垢版 |
2021/10/21(木) 11:19:37.65ID:l0SlZ35R
ババ抜きはOld maidの日本語訳だよ
セクシズムやエイジズムはポリコレの立場から見てどうだろうね
2021/10/21(木) 12:39:37.82ID:u1ltZUWw
regexで\dを使いたい場合はどうやるん?
2021/10/21(木) 14:10:28.52ID:ObBh/rk9
https://cpprefjp.github.io/reference/regex/basic_regex.html
2021/10/21(木) 17:33:55.95ID:MfhbDLcG
>>812
その比較でなんで fread だけ遅いんだ?と思ってコード見たら fread じゃなくて fgets になってた。
あと read_cpp_standard() の if (std::cin.fail()) もたぶん f.fail() の間違い。
819デフォルトの名無しさん
垢版 |
2021/10/21(木) 18:24:19.20ID:/1ln80gU
>>815
フェミが言葉狩りのネタにしないのは何故
2021/10/21(木) 18:42:48.64ID:7ERuyWg6
言葉狩りなんてないから
821デフォルトの名無しさん
垢版 |
2021/10/21(木) 18:56:39.47ID:ObBh/rk9
>>818
thx
>>812のコードは脳内破棄してくれ
指摘された部分を修正した
https://ideone.com/DoI3ww

同環境での測定結果が↓
214
213
214

freadだとバッファリングされるからその分遅いのかと勝手に思ってたらそんなところから間違ってたとはすまんw
822デフォルトの名無しさん
垢版 |
2021/10/22(金) 00:41:05.61ID:bIdSm1HR
BB抜きが有ってGG抜きが無いのは差別
823デフォルトの名無しさん
垢版 |
2021/10/22(金) 00:43:55.21ID:bIdSm1HR
>>821
fread最強でFA
2021/10/22(金) 01:17:58.50ID:JLUkeFzw
freadのバイナリな
DMA効くのは
テキストはゴミ
2021/10/22(金) 02:55:23.69ID:ugOmuUc2
>>822
ジジ抜きもあるよ。
ジジ抜きはジョーカーを使わない。
適当な札を一枚抜いておいて組にならない札を最後まで持ってた奴が負け。
どれが負け札なのか最後までわからないというのがゲームの面白い部分。

ちなみに日本語でジジ抜きと呼ばれているゲームこそが Old maid (行き遅れ、お局様) の本来のルールで、
ペア (結婚相手) がないことを Old maid に喩えた命名になっている。
2021/10/22(金) 05:43:15.83ID:I4IH0MDY
C++20ちょっと書き始めたらvscodeのインテリセンスが何でもないところにエラーの波線出しまくってくる
2021/10/22(金) 07:07:31.23ID:viI1I/mh
DMAか、懐かしい
2021/10/22(金) 12:50:15.03ID:xpSH/+fs
>>826
どの環境でそうなる?
2021/10/22(金) 13:37:10.17ID:I4IH0MDY
>>828
OS: Windows 8.1 (64 bit)
コンパイラ: MinGW GCC 11.1.0

文句を言ってくる拡張機能は多分普通の"Microsoft C/C++ 拡張機能"でコードの例としては
https://wandbox.org/permlink/Fcqjvfqt8rWVqren
こんな感じ

エラーは
operator<=>: 戻り値の型だけで識別される関数はオーバーロードできません
requires(1個目): こちらでは requires 句は許可されていません (テンプレート関数ではありません)
vec: エイリアス テンプレート "vec" の引数リストがありません
v: ';' が必要です
という感じ

まあエイリアスのやつはC++17でも言えるけど
2021/10/22(金) 23:23:13.68ID:Q/4+pM2R
Pythonのリストのように不定型の配列を作るにはどうすればいいですか?

vector<int> a;
vector<double> b;
vector<vector<any>> hoge;
hoge.emplace_back(a);
hoge.emplace_back(b);

みたいなことをしたいですが、エラーになりました。
最終目的は、
void f(vector<vector<any>>, vector<vector<any>>)
のような不定型配列を複数引数に取る関数を作りたいです。
2021/10/22(金) 23:45:34.05ID:vgFDGRgE
std::variantつかうとか
2021/10/23(土) 01:05:44.90ID:UQ/XjfNb
>>830
出来るといえば出来るんだが、動的型っぽいことを C++ でやろうとすると煩雑だよ。
std::any は何でも格納できるが使うときには結局は元の型として取りださないといけない。
格納することが出来たとして、その後にどういう風に使うのかによってデザインの仕方がかわってくる。
2021/10/23(土) 01:33:33.73ID:0KDU0Kot
>>830
C++17以降、へえ、こんなこともできるんだ… https://cpprefjp.github.io/reference/variant/variant.html
https://ideone.com/G8IPFR
>>831
ありがとうございます!
2021/10/23(土) 01:34:50.09ID:0KDU0Kot
>>832
うん、実用に供するまでには結構大変そう、使い道がわからん…
2021/10/23(土) 01:57:47.58ID:UQ/XjfNb
>>834
クラスの設計段階で抽象クラスとの継承関係を作っておくだとかいった方法で多相にするのが
旧来からの方法で、それができるならそのほうがまともなものになると思うんだが、
そうは言ってもユーザーからは弄れない既存のクラスをどうしても使いたいということも無くはない。

根本的な部分をいじれないときに場当たり的にどうにかするよりは std::any や std::variant を使ったら
少しはマシかもねという程度の話で、あまり積極的に使うようなものではないというのが私の感触だな。
2021/10/23(土) 08:10:22.62ID:LycCK1PV
void*よりはちょっとマシって程度の感覚だな
2021/10/23(土) 10:04:52.59ID:rMqegMI3
>>832
その後の使い方は、基本的には
全要素をany_castでstringにして使うつもりです。
不定型可変長のデータを受け取ってcsvファイル出力に使いたい感じです。
2021/10/23(土) 10:05:50.17ID:bwy1yWHL
void*「むかしはあんなに愛してくれたのに…」
2021/10/23(土) 11:08:12.01ID:FGy8rv7m
>>830
any使うんだったら、
vector<vector<any>> hoge;
じゃなくて
vector<any> hoge;
じゃない?
2021/10/23(土) 11:40:12.00ID:KcnUiVki
>>835
>>833じゃないけど>>833のdump()を例えば
template<class... Args>
void dump(const std::variant<Args...>& e) {
std::visit([](const auto& x){
std::cout << " " << x << std::endl;
}, e);
}
template<class V>
void dump(const std::vector<V>& v) {
for (const auto& e: v) {
dump(e);
}
}
みたいにするんなら
class Dumpable {
virtual void dump() = 0;
};
みたいな抽象クラス作って素直にArgsの各classが継承(実装)した方がいいと思うってこと?
2021/10/23(土) 13:07:50.50ID:UQ/XjfNb
>>840
そう。 クラスごとに違う挙動が必要ならその違いはクラスの中に隠蔽されているべきで、
クラスを使う側で分岐するのはなんかちょっとあれだなという感じ。

型を調べて分岐するようなコードが嫌だから動的な型を調べる機能を意図的に入れなかった話は D&E にも書かれてる。
(最終的には typeid が導入されてしまったけど……)
ただそれは「型を追加したくなったら分岐も増やすのはめんどいしミスしそう」みたいな話なので、
十分に賢いユーティリティが標準で用意されている今ならそれほど強い動機でもないんだけどね。
842デフォルトの名無しさん
垢版 |
2021/10/23(土) 13:12:23.67ID:quaWTEll
C++はパラメトリック多相が無いからこういうのは面倒だよね。
とりあえずはstd::vector<std::function<std::string()>>に[v](){ return std::to_string(v); };
あたりを入れとくのが簡単かね。

conceptを「その制約を持つクラスの総称クラス」としてshared_ptrあたりで指定できるようになると便利なんだけどなぁ。
concept_shared_ptrとか用意してくれんかね。
2021/10/23(土) 13:16:46.64ID:UQ/XjfNb
>>837
any_cast での取り出しは「元の型」でなければならず、
string に変換可能な型であっても any_cast<string> は出来ない。
(やったら例外が飛ぶ)

最終的に文字列になると決めているなら文字列にしてから格納したほうがすっきりするんじゃないの。
2021/10/23(土) 14:23:02.68ID:KcnUiVki
>>841
まあそうだよね。ありがとう。
2021/10/24(日) 08:17:03.78ID:mo2+vXTQ
>>771-772
以下のような場合についてBarクラスがRAIIであるというだけでどう例外安全にできるのかお考えをお聞かせ願えますか
void foo() {
 {  // 何かのコードブロック (try { } catch { } のtry{ } とかでも良い
   Bar x, y, z;
    (例外を生じる可能性があるコード)
   アプリケーション固有の別スレッドXにイベントなりシグナルを送る
 }
}

>>723
上に書いたようなケースを踏まえてっ例外安全に言及している>>720>>721に対して
理解しいないまま捨て台詞を残して逃走した>>722とか、
2021/10/24(日) 08:20:03.55ID:mo2+vXTQ
>>772
コードブロック内のreturnがあるかもしれないんならチェックすれば良いやん?
>>763は普通の人ならチェックするでしょ、という主張

ところが>>722のような例外安全主義者ときては、RAII = 例外安全、で脳がショートしているのや
多分周りも能力に忖度して大した課題を与えていないんだと思う
2021/10/24(日) 08:40:20.31ID:i4dOTOfz
上では例外安全にするとかしないとか言っていたような気がしたが少し主張が変わったのかな。

- 例外安全を求めるのは当然
- RAIIを使えば比較的例外安全を保証しやすい
- だからといってRAIIを使えば自動的に例外安全になるわけではない

結論としてはこんな感じだと思うが。
2021/10/24(日) 08:41:27.07ID:7jz7Y9vl
チェックして例外出さないと解放されないコード書いたのか…
2021/10/24(日) 09:13:23.68ID:1SVJ9Wvp
そりゃ例外安全もRAIIも魔法じゃないんだから使えば即安全になるというわけじゃないわな
「ちゃんと使えば」をすっ飛ばして>>845みたいなことを言い出すのも一種の思考停止だろうと思うわ
2021/10/24(日) 09:51:02.52ID:v4numFpL
>>845
Barのデストラクタの責務は自分が確保したリソースをリークしないことだけだ
オブジェクトの外側でやってるスレッド間通信のことなんかBarは知らんし別に手当するだけの話

逆に聞くがRAIIを嫌がってBar* x = new Bar;とかにしたらなんか事態改善すんの?スレッド間通信を簡潔に書くための役に立つの?
2021/10/24(日) 10:24:44.80ID:P2kmr3bK
そもそもRAIIが例外安全のためっていうイメージ全くないんだけど
リソースのお片付け(≒メモリリーク防止)が主目的ちゃうん?
2021/10/24(日) 10:36:38.75ID:i4dOTOfz
例外が発生するとリソースを片付け損ねる場合があるってのが例外安全を欠く一番よくあるケースだと思うけど。
主目的がどうとかは別として。
2021/10/24(日) 10:45:51.44ID:NLtlOSxj
>>845
例外を生じた場合でもXとなんらかの通信を行うべきなら
thread_connectionみたいなクラスを作ってデストラクタに整合性を保つためコードを書くのがいいかな
「アプリケーション固有の〜を送る」の部分にはそのオブジェクトのメソッド呼び出しにしておく
例外発生時にはデストラクタによってXスレッドに異常を通知してXスレッドが持つ状態の整合性を確保してもらう

Xに通知するのが単なる終了通知なら(成否を区別して処理しなくていいなら)全部デストラクタでいいかもね
2021/10/24(日) 10:47:45.55ID:KyFc3YJo
結局コードがないのでまた空中戦になってますね
2021/10/24(日) 11:38:44.49ID:IQSwOnqn
例外でデストラクタ呼ばないケースなんてあるんですか?
プログラム自体が止まるのは別として
2021/10/24(日) 12:07:45.68ID:KyFc3YJo
リマインダー>>731
2021/10/24(日) 14:38:53.43ID:KyFc3YJo
これg++ 9.3だとstd::endlがなぜかconst variant<>と思われてエラーになってるみたいなんだけど、なぜ?

#include <variant>
#include <iostream>
using namespace std;
template<class C, class... Args>
C& operator<<(C& out, const variant<Args...>& v) {
visit([&](auto& x){out << x;}, v);
return out;
}
int main() {
cout << endl;
return 0;
}

https://godbolt.org/z/dbodW3xfG
2021/10/24(日) 15:13:35.43ID:rOnHPdOM
>>838
「「最初から void * な実体」は作らない」「void (*)(void *, ...) くらいまでがせいぜいだ」というように努めていた私は愛し方が足りなかったのでしょうか?
最近の愛し方:https://mevius.5ch.net/test/read.cgi/tech/1624028577/305
2021/10/24(日) 18:37:46.86ID:SzIAMYLD
>>857
std::endl は関数テンプレートなので型と比較しようとするとインスタンス化に失敗するというエラーだと思う。
(std::endl を普通に使うときは左辺の型を利用して推論される。)
型を明示して渡せば variant との比較に失敗して通常の改行として解釈してくれる。

#include <variant>
#include <iostream>
using namespace std;
template<class C, class... Args>
C& operator<<(C& out, const variant<Args...>& v) {
visit([&](auto& x){out << x;}, v);
return out;
}
int main() {
cout << static_cast<std::ostream&(*)(std::ostream&)>(std::endl);
return 0;
}
2021/10/24(日) 19:35:48.44ID:KyFc3YJo
>>859
う〜ん、よく分かりませんね。確かに勝手にendlは[with _CharT = char; _Traits = std::char_traits<char>]なbasic_ostreamを
引数にとって返すと想定しちゃってましたが、その時点でインスタンス化しようとしてエラー出す理由が分からない・・・

例えばテンプレート引数を直指定しても

#include <variant>
#include <iostream>
using namespace std;
template<class C, class... Args>
C& operator<<(C& out, const variant<Args...>& v) {
visit([&](auto& x){out << x;}, v);
return out;
}
int main() {
cout << endl<char>; // ここが違う
return 0;
}

同様にエラーのままでした。castしたときだけなぜ判定失敗してくれるのかもう少し考えてみます。
ありがとうございました。
2021/10/25(月) 00:43:36.43ID:dRHq7DJG
>>860
左辺が曖昧だからかもしれない。
左辺の型を std::ostream で固定すれば通る。

#include <variant>
#include <iostream>
using namespace std;
template<class C, class... Args>
std::ostream& operator<<(std::ostream& out, const variant<Args...>& v) {
visit([&](auto& x){out << x;}, v);
return out;
}
int main() {
cout << endl<char>;
return 0;
}

でもこのとき型変数 C は不要だなと思って class C を削るとエラーになるんだよな。
なんだかよくわかんないね。
2021/10/25(月) 02:18:03.94ID:LmZJdmU+
>>861
度々ありがとうございます。再現確認したところ、確かに余計なテンプレート引数が1つあるだけでこのエラーが出ないみたいですね。
試しに元のコード(>>857)に余計なパラメータを1つ入れるだけでも通りました。

#include <variant>
#include <iostream>
using namespace std;
template<class T, class C, class... Args> // ダミーパラメータT追加
C& operator<<(C& out, const variant<Args...>& v) {
visit([&](auto& x){out << x;}, v);
return out;
}
int main() {
cout << endl;
return 0;
}

ほんとによく分かりませんね。
castの件は第2引数のvがテンプレート関数でなければ弾けるということのような気がします。
https://onlinegdb.com/ol3BYChIx
2021/10/25(月) 02:19:56.83ID:LmZJdmU+
最後のコードは右上の設定ボタンから -std=c++17 を追加することで実行できます。
2021/10/25(月) 13:57:01.70ID:p1HT8A4i
iostreamのシフト演算子オーバーロードは文句を言われてるがrangesのoperator|のオーバーロードはどうなんですかね
2021/10/25(月) 14:01:06.87ID:dRHq7DJG
感覚的にはまあ順当だろうと思う。
日付やパスで / を使うのに比べればよっぽど……。
2021/10/25(月) 15:38:37.13ID:x4U5y7kU
組み込みの意味を持たないオーバーロード専用演算子があれば良かったのにな
用意しておかなかったのはC++の初期デザインの失敗だったと思う
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況