2ちゃんねる ■掲示板に戻る■ 全部 1- 最新50    

0からの、超初心者C++相談室

696 :デフォルトの名無しさん:2023/11/28(火) 18:50:50.78 ID:dISnZSIc.net
そら綺麗に一つのcppに全部そのクラスの実装を切り分けてるならcpp内にstaticでいいだろうけどね

697 :デフォルトの名無しさん:2023/11/28(火) 20:09:09.84 ID:vcMwjchf.net
そんな巨大なクラスは設計が間違ってないか?

698 :デフォルトの名無しさん:2023/11/28(火) 20:12:44.23 ID:bqHRuT95.net
>>677
> 「ダブルポインタ」ってのも可笑しな使われ方してることが数多く観測される

それなw
初心者ほどこの用語を使ってるように見える
初心者が集まるところでこれを流布してるやつがおるんやろな
ポインタへのポインタっていうスケーラブルな定義が理解できてなくて
アスタリスクいっこのポインタと、二個のぽいんたがある!って感じなんやろな

699 :はちみつ餃子 ◆8X2XSCHEME :2023/11/28(火) 20:20:10.37 ID:mRTkdYl9.net
>>697
この >>696 の言は逆のことを言ってると思う。
ひとつの翻訳単位にたくさんのクラス (の実装部分) を書くこともあるから
ファイルスコープにしたらスコープの範囲が広すぎる (制限にならん) やんけと言ってるように読める。

700 :デフォルトの名無しさん:2023/11/28(火) 20:27:35.33 ID:dISnZSIc.net
>>697
巨大とかじゃなくて、あんたの考えてるであろう1ヘッダに1ソースってのも指針としてはもちろん良いんだけど(そして質問者のケースに合ってるならいいけど)
例えばクラステンプレートになると、ソースに実装を書けないからヘッダのどこか(ヘッダからインクルードしてユーザーに見え辛い場所には出来るが)で実装を書くことになる
そうなるとその実装からソースファイル内のstaticな値など見えるわけがないだろ

701 :デフォルトの名無しさん:2023/11/28(火) 20:29:47.21 ID:dISnZSIc.net
>>699
もちろんそれもある

702 :デフォルトの名無しさん:2023/11/28(火) 20:57:18.00 ID:dISnZSIc.net
まぁどれを選ぶかは本人の都合だけど、クラス定義の中にprivateで書くのが自然っちゃ自然な希ガス

703 :デフォルトの名無しさん:2023/11/28(火) 21:00:29.03 ID:HOP5xTTo.net
>例えばクラステンプレートになると、ソースに実装を書けないから

C++の設計ミスだな
特にテンプレ

704 :デフォルトの名無しさん:2023/11/28(火) 21:55:43.79 ID:vcMwjchf.net
テンプレートは単なる#defineだからなぁ
あんなもん#defineでの置き換えによる副作用を引き起こす悪習の最たるもんだよ

705 :はちみつ餃子 :2023/11/28(火) 22:43:12.61 ID:mRTkdYl9.net
一応はモジュールの概念の導入でちょっと良くなっているはずだが皆でこぞって移行するってほどには全然なってないからそこまで魅力的とは思われてないんやろね。
従来のスタイルと共存できるようにするのは C++ の立場では当然ではあるものの、悪い部分も捨てきれないことになりがち。
コンパイラのサポートもあまり熱心ではない(?)ような雰囲気だからそこも不安だし。

706 :デフォルトの名無しさん:2023/11/28(火) 23:00:59.77 ID:5UazaCro.net
どうも>>680です。
2のクラス名あり版でビルド通りました。

-sample.h
class sample_1 {
int a;
static const int TBL[3];
public:
sample_1();
};

-sample.cpp
#include "sample.h"
#include <iostream>

const int sample_1::TBL[3] = {1,2,3};

sample_1::sample_1() {
a = 2;
std::cout << TBL[a] << std::endl;
}

-main.cpp
#include <iostream>
#include "sample.h"

int main() {

sample_1 sa;
return 0;
}

707 :デフォルトの名無しさん:2023/11/28(火) 23:06:12.31 ID:5UazaCro.net
sample.hにTBL宣言なしで、

sample.cpp
#include "sample.h"
#include <iostream>

static const int TBL[3] = {1,2,3};

sample_1::sample_1() {
a = 2;
std::cout << TBL[a] << std::endl;
}

でもOKでした。こちらのstaticはC式の使い方ですね。

私はTBLが.hに現れない上の書き方がいいと思いますが、これを最適としてよさそうですか。

708 :デフォルトの名無しさん:2023/11/28(火) 23:19:21.29 ID:dISnZSIc.net
解決おめ、自分の用途に合うと感じるならそれがベストと思うよ

709 :デフォルトの名無しさん:2023/11/29(水) 06:23:02.71 ID:n75oaT1g.net
h に static 描くと単に相互干渉しないってだけで
インスタンスは造られまくって無駄リソース出まくるんじゃね

710 :デフォルトの名無しさん:2023/11/29(水) 09:24:39.36 ID:5+1qDy8t.net
奴は人の書き込み見ちゃいないよw

711 :デフォルトの名無しさん:2023/11/30(木) 22:28:52.60 ID:p6G1t8dm.net
sizeof(クラス名)を活用できる場面はありますか。
メンバによってはCのsizeof(構造体名)と同じ使い方ができると思いますが、
クラス一般について考えると思いつきません。

たとえば
std::string name;
がメンバ変数にあるともう、クラスのサイズは不定になりそうです。
あっ、new は・・・いや、mallocと違ってサイズ指定は不要ですね。

712 :デフォルトの名無しさん:2023/11/30(木) 22:39:03.15 ID:jq+Wc58z.net
>>711
>std::string name;
>がメンバ変数にあるともう、クラスのサイズは不定になりそうです。
確認してみましょう!

713 :はちみつ餃子 ◆8X2XSCHEME :2023/11/30(木) 23:39:52.07 ID:3QI4e6Tt.net
>>711
sizeof 演算子の適用結果は定数であることが保証される。
定数式として使うことができる。
std::string なども型の大きさが変動したりはしない。

C ではオペランドが VLA のときは sizeof の結果は定数にならないのだけれど C++ には VLA がないのでそういう例外はない。
(実際には処理系の拡張として VLA を使える場合もある。)

メモリアロケーションまわりを自分でコントロールする機会があれば普通のクラスの大きさを知る必要がある場合もなくはない。
それほど機会は多くないだろうけど。

本来 (?) の用途とは違うところで使われる場合もあって、
いわゆる SFINAE のトリックで sizeof が使われることもそれなりにある。

714 :デフォルトの名無しさん:2023/11/30(木) 23:55:15.59 ID:p6G1t8dm.net
>>713
高度な領域では使う場面はあるが、入門者には当分、なさそうですね。ありがとう。

715 :デフォルトの名無しさん:2023/12/01(金) 10:06:48.86 ID:NZuUNSBe.net
おまえら、stdとboostどう使い分けてる?

716 :デフォルトの名無しさん:2023/12/01(金) 13:58:15.55 ID:aU4DjGEJ.net
>>714
stringも実際には確保したメモリのポインタと文字列サイズを持ってるだけ(だけではないけど簡単に言えば)なので
Cの構造体と大して変わらんのよ

717 :デフォルトの名無しさん:2023/12/02(土) 07:29:47.55 ID:qIqFVuKn.net
まず鍵を与え、文字列を暗号化等して暗号文文字列を返したい。

暗号化ユーティリティ風のクラスをつくり、鍵とstringを渡す案 (1)と、stringを継承して鍵保持メンバ関数と暗号化メンバ関数を追加する案(2)を思いつきました。

どちらがでも実現できるように思いますが、何か設計のポイントはありますかね。
暗号化等には既製ライブラリ使います。

718 :はちみつ餃子 ◆8X2XSCHEME :2023/12/02(土) 09:03:43.92 ID:w8ZlbPjQ.net
>>717
設計は総合的な判断だから単発の事情では判断しづらいというのは前置きとして書いておくけど、原則的には非メンバ関数として実装するほうがよい。
というよりも継承を使うほうが悪い。
「こういうメンバ関数があると便利」ということだけが理由なら継承を使うのは好ましくない。

プロジェクトの中で使う文字列を暗号化機能付きの文字列クラスで一貫して扱うならそれはそれでそんなに悪くないけど、通常は std::string 型のオブジェクトがあってそれを暗号化したいだけなのに別の型に変換にするという手間をかけるのがユーザーにとって便利だと思う?

719 :はちみつ餃子 ◆8X2XSCHEME :2023/12/02(土) 11:45:21.73 ID:w8ZlbPjQ.net
他の選択肢としてはストリームのアダプタにするとかいう方法も思いつく。
極端に大きなデータ (メモリに格納するには無理のある大きさ) にも対処したい場合は入出力と並行して処理することになるから、普通にストリームに書き出すのと同じように使ったら勝手に暗号化されてるというのは使う側としては楽でいい。
自分が使うものならそういう余計な抽象化層を挟むのは手間なだけかもしれないし、匙加減は微妙なところ。

720 :デフォルトの名無しさん:2023/12/02(土) 12:16:48.61 ID:0tC7Yjqi.net
sqliteとかの(暗号化もあるけど)暗号化しないバージョンのDBを使ってて
書き込むとき勝手に暗号化してくれると有難いな

721 :デフォルトの名無しさん:2023/12/02(土) 13:25:55.77 ID:JgaBxQHi.net
ここはプログラム技術板だぞ 自分で作れ

722 :デフォルトの名無しさん:2023/12/03(日) 06:49:36.39 ID:xZHPSaOR.net
このスレはC++の話ではない書き込みが多すぎる

723 :デフォルトの名無しさん:2023/12/03(日) 11:07:00.27 ID:QTewqrs7.net
C++の守備範囲が広いんよ

724 :デフォルトの名無しさん:2023/12/03(日) 21:36:41.23 ID:kkqQUehZ.net
>>718
ありがとう。
非メンバ関数として実装、と見て最初はなぜ?と思いましたが、確かに文字列変換だけでクラスオブジェクトはいらないですね。
string 暗号化(鍵, 平文);
だけあれば十分だと。

725 :デフォルトの名無しさん:2023/12/04(月) 21:09:04.65 ID:wzr7hFvb.net
msys2で開発環境を作りたくて
Windows10上にmsys2をインストールしてそのうえにpacmanからmingw-w64-x86_64-toolchainの最新版をインストールして
g++でコンパイルしてHello Worldを出力するところまではうまく行ったのですが
std::ifstream ifs("hoge.txt");
のような実行ファイルと同じ場所にある、あらかじめ用意したテキストファイルを読み込むだけのコードを書いてもファイルの読み込みに失敗します。
fstreamだけの問題ではなくfilesystemあたりをインクルードして適当な関数でテストしてもファイルが存在しないことになっていました。
どこで質問するのが適切なのかも見当がつかない状態なのですが原因に心当たりがある方がもしいらっしゃったら教えて頂けないでしょうか?

726 :デフォルトの名無しさん:2023/12/04(月) 22:11:21.42 ID:+6ZMbPCa.net
エラーメッセージは?

727 :はちみつ餃子 ◆8X2XSCHEME :2023/12/05(火) 00:16:37.88 ID:z5PiblaY.net
msys2 環境は数種類のモードがあるはずだがどれで起動した?

728 :デフォルトの名無しさん:2023/12/05(火) 04:57:07.09 ID:DXGBHl1O.net
実行ファイルの場所がカレントになってないんだろ
getcwd()してみ

729 :728:2023/12/12(火) 14:02:16.36 ID:haJQSzRG.net
エラーは何もなくて変数に何も格納されてない状態だったので原因よくわかりませんでしたが
今回は>>728さんの言う通りになっていて解決できました
まだmsys2自体の仕様も十分に理解してなくて手が回っていない状態なのでこれでいったん失礼します
ありがとうございました!

730 :デフォルトの名無しさん:2023/12/12(火) 15:14:22.81 ID:bMo3JLCK.net
GUIから起動するとカレントディレクトリがホームになるんだったっけ?

731 :デフォルトの名無しさん:2023/12/13(水) 15:23:50.85 ID:Xh1qTD5r.net
OSの事情でカレントが簡単に移動してしまうのがめんどいな

732 :デフォルトの名無しさん:2023/12/13(水) 16:17:33.78 ID:b3+IUHNQ.net
プログラムの実行に必要な設定ファイルやデータファイルはカレントディレクトリではなく実行ファイルのパスを基準に決めたほうがいいね

733 :はちみつ餃子 ◆8X2XSCHEME :2023/12/13(水) 17:12:54.61 ID:vPv7AHCs.net
設定ファイルの類いは AppData フォルダに置くのがこのましいということになってる。
アプリケーションインストール用のフォルダ Program Files は書き込み権限が制限されているからそこに設定ファイルは置けない。
逆にどうしてもアプリケーションと設定ファイルを同じフォルダに置きたいなら Program Files にはインストールできない。
Msys2 内で使うソフトならホームディレクトリ (windows のホームディレクトリではなく msys2 が設定するホームディレクトリ、環境変数 HOME で取得できる) に設定ファイルを置くのが基本的な習慣。

734 :デフォルトの名無しさん:2023/12/13(水) 17:14:51.41 ID:Xh1qTD5r.net
起動時の引数や 自分のフルパスを取得するAPI経由で
実行ファイルのある場所を基点にどうこうすることが多いわ (Windows

unix だと usr と bin で分ける文化があるからそういうのはどうなってるんやろか
起動時のカレントのまま?

735 :デフォルトの名無しさん:2023/12/13(水) 17:20:10.83 ID:b3+IUHNQ.net
>>733
それはインストーラー使うアプリでしょ?
XCOPYインストールアプリの話だよ

736 :デフォルトの名無しさん:2023/12/13(水) 17:23:03.86 ID:HyXW4bJ5.net
カレントじゃ無くて、アプリが実行されたディレクトリに一緒に置いとくもんだろ?
ユーザー毎に違う設定にしたいなら、各ユーザーのホームディレクトリだろ?

737 :はちみつ餃子 :2023/12/13(水) 18:03:20.75 ID:vPv7AHCs.net
>>736
基本的にはそうだけどパッケージマネージャの管理方式との相性があったりする。
scoop で管理するなら設定ファイルも含めてひとつのフォルダに入れるほうが都合が良いと思う。
Msys2 内で pacman で管理するなら unix 風の流儀のほうが自然だし。

738 :デフォルトの名無しさん:2023/12/13(水) 23:12:49.25 ID:zjCiNOvz.net
グローバル位置に宣言したオブジェクトはmain前にコンストラクタが実行されますね。
仕様ではmain前に実行ということのほかに何か規定はありますか。

ある処理系で、main先頭である処理を呼び出すと成功するが、その処理を上記のコンストラクタから呼び出すと失敗するということがありました。

739 :はちみつ餃子 ◆8X2XSCHEME :2023/12/14(木) 00:23:02.09 ID:GWgG2Hfk.net
>>738
ややこしい規則が色々あってここには書ききれないがおおざっぱにはこんな感じかな。

・ 定数初期化が終わってから動的初期化がされる
・ 動的初期化でも条件が揃ったときは静的初期化扱いで早めに初期化する最適化をしてもよい (しなくてもよい)
・ 翻訳単位内の初期化順序は定義が現れた順序
・ 翻訳単位をまたぐとどちらが先に初期化されるかは規定されていない

特に翻訳単位を跨いだら決まってないってのは引っかかりがちなポイントで、
強い依存関係のあるものはあまり細かく分割しないほうがやりやすいと思う。

740 :デフォルトの名無しさん:2023/12/14(木) 01:04:36.74 ID:X6Ol8Z5z.net
普通は、WSL2 でLinux を使う

MSYS2/MinGW の利点は、
hypervisor で、2つのOS を起動しないから軽い

WSL2 では、Linux側から、Windows 側のアプリも起動できる。
ただし例えば、powershell ではなく、powershell.exe と拡張子も付ける

例えばpowershellで、Windows側のフォルダ内の一覧を表示して、Linuxのgrep で絞り込む

/mnt/c/Users/ユーザー名/Documents$ powershell.exe ls | grep クイ

出力
d----- 2015/10/13 13:52 クイズ

VSCode の拡張機能・Code Runner は、
右クリックメニューから、選択したコード、またはファイル全体を実行する

この設定をチェックしておく
Code-runner: File Directory As Cwd
Whether to use the directory of the file to be executed as the working directory.

そうすると実行時にcd で、そのファイルがある場所へ、カレントディレクトリを移動してから、
そのファイルをコンパイルして実行する

設定項目、executorMap には、多くの言語の実行コマンドが書いてある。
"code-runner.executorMap": {

"c": "cd $dir && gcc $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
"cpp": "cd $dir && g++ $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",

741 :デフォルトの名無しさん:2023/12/31(日) 22:48:46.98 ID:tpduSr4A.net
相談室から誘導されたのでこちらで
http://mevius.5ch.net/test/read.cgi/tech/1698705458/104

buf_にPODではないオブジェクトが含まれる可能性がある場合、この領域をどのようにcopyしたりmoveすればよいでしょうか?

742 :デフォルトの名無しさん:2024/01/01(月) 01:29:30.25 ID:/rCM9JK/.net
このスレッドはゼロからC++と言っているが、C言語を知っている前提になっているよなw

743 :デフォルトの名無しさん:2024/01/02(火) 11:00:49.80 ID:TDOOgc4U.net
ワシも割と長く底辺コピペプログラマだけどなんでそんな詳しくなれるの?ってなる
有能と俺みたいな無能はどこでプログラマの生き方をたがえたのか

744 :デフォルトの名無しさん:2024/01/02(火) 20:21:16.21 ID:G9bvfkvl.net
>>743
頭の出来で決まっているからね

義務教育レベルで脱落した人間、日本語能力に問題がある人間は、プログラマーとしても問題がある。

745 :はちみつ餃子 :2024/01/02(火) 21:40:20.68 ID:RkRzwbey.net
知識は入れないと増えないというすごく当たり前の話。
長く放置してたら勝手に増えるなんてことはないよ。

746 :デフォルトの名無しさん:2024/01/03(水) 08:18:02.54 ID:3n4RUKo6.net
ガキの頃からマイコンBASICマガジン見てたけど
PCなかったしポケコンはあったからたまにあるポケコンゲームのソースをポチポチ入力してたけどそれで何かの知識になったか言われたら何にもならんかったな

747 :デフォルトの名無しさん:2024/01/03(水) 08:26:31.48 ID:uKn1SmuA.net
糞コテが

748 :デフォルトの名無しさん:2024/01/03(水) 13:07:46.32 ID:3mJitcl/.net
>>746
SHARPのポケコンでマシン語使ってシューティングゲーム作ったけど?

749 :デフォルトの名無しさん:2024/01/03(水) 13:17:11.92 ID:SgwYv7hO.net
ポケコン触ってたころが一番楽しかったです
手の中に物理キーボードと実行環境があるんだもん
一生遊べるよ

750 :デフォルトの名無しさん:2024/01/03(水) 14:56:53.56 ID:giTORTIB.net
>>741
memcpyでなくちゃんとplacement newでコピーorムーブコンストラクタ走らせればいんじゃね?

751 :デフォルトの名無しさん:2024/01/10(水) 03:00:04.91 ID:lNNg6PiH.net
Class Hogeの中でたくさんのFugaを管理するために
std::vector<std::unique_ptr<Fuga>>というメンバ変数を作りました
可変長引数テンプレートで複数のstd::unique_ptr<Fuga>を受け取るコンストラクタを書こうとしたのですが
std::unique_ptrがコピー禁止のためうまくいきませんでした。
Hoge(Args&&... args)
という形で右辺値参照を受け取ってうまいことムーブしてClass Hogeを初期化する方法ってありますか?

752 :はちみつ餃子 ◆8X2XSCHEME :2024/01/10(水) 04:36:30.64 ID:BOjhYgCx.net
>>751
できると思うけど、何をやりたくて何が上手くいかなかったのかイマイチわからない。
出来なかったコードをみせて。

753 :デフォルトの名無しさん:2024/01/10(水) 11:27:22.10 ID:lNNg6PiH.net
>>752
class Fuga
{
int placeholder;
};
class Hoge
{
public:
std::vector<std::unique_ptr<Fuga> > vec;
template<class... Args>
Hoge(Args... args)
{
vec = {args...};
}
};
int main()
{
/*Fugaを何個か作成*/
auto p1 = std::make_unique<Fuga>();
auto p2 = std::make_unique<Fuga>();
auto p3 = std::make_unique<Fuga>();
/* 中略 色々処理
処理が終わったらHogeの中にFugaをまとめて放り込みたい*/
Hoge hoge(p1,p2,p3);
}

こういうものを書いたらunique_ptrがコピー禁止でエラーになったのでムーブにしたいけど書き方がわかりませんでした。

754 :はちみつ餃子 ◆8X2XSCHEME :2024/01/10(水) 12:45:18.04 ID:BOjhYgCx.net
>>753
この場合は initializer_list が問題。
initializer_list を経由するとムーブ可能/コピー不可な型を扱えない。
initializer_list を経由しない形にすればよいので要素を emplace_back で
入れる形にするなどの対処法が考えられる。

#include <memory>
#include <vector>

class Fuga {
int placeholder;
};

class Hoge {
public:
std::vector<std::unique_ptr<Fuga> > vec;
template <class... Args>
Hoge(Args&&... args) {
(..., vec.emplace_back(std::forward<Args>(args)));
}
};

int main() {
/*Fugaを何個か作成*/
auto p1 = std::make_unique<Fuga>();
auto p2 = std::make_unique<Fuga>();
auto p3 = std::make_unique<Fuga>();
/* 中略 色々処理 */
// std::move で右辺値にキャスト
Hoge hoge(std::move(p1), std::move(p2), std::move(p3));
}

755 :デフォルトの名無しさん:2024/01/12(金) 09:52:36.06 ID:Umd8uX9b.net
c++で日本語の連想配列ってあります??

756 :デフォルトの名無しさん:2024/01/14(日) 15:30:33.22 ID:O4q5V5KL.net
>>755
std::mapじゃだめなん?

757 :デフォルトの名無しさん:2024/01/16(火) 21:37:05.24 ID:eUaXJLuy.net
>>754
無事に動作させることができました。ありがとうございます!

758 :デフォルトの名無しさん:2024/01/20(土) 18:17:15.80 ID:9qysS+ur.net
時間のかかる処理があり、それが現在のスレッドをブロックして欲しくないので
その処理の部分に関してstd::async()の利用を検討していますが、
これって戻り値(future 型)でモニターしないといけない感じですか?
上記の処理はいつ終わるかは気にしないので別スレッドに投げっぱなし?で構わない
のですが... pthread_detach()的な?

759 :はちみつ餃子 :2024/01/21(日) 12:43:25.73 ID:4rk7TZPC.net
>>758
std::thread のメンバ関数に detach はあるけど、期待するのはこういうこと?

ただ、メインスレッドが終了すれば他のスレッドが稼働中でもプロセス終了処理に入るし、
プロセス終了処理の中で標準ライブラリの後始末している最中に他のスレッドが
標準ライブラリを使うようなことがあると破綻するかもしれない。

強引に終わらせて良いなら std::quick_exit で即死させるという方法も取れるが、
基本的にはプログラムを終わらせるときには全てのスレッドを終了させて (終了を待って) おくのが
普通だと思う。

760 :デフォルトの名無しさん:2024/01/21(日) 21:48:26.38 ID:zlvjOB5M.net
>>758ですが、お返事ありがとうございます。

はい、とりあえず thread::detach() を使うようにしました。1つの疑問は、
https://ja.cppreference.com/w/cpp/thread/future/~future によると
> ただし、その共有状態が std::async によって作成され、まだ準備完了になっておらず、これがその共有状態への最後の参照である場合は、ブロックする可能性があります。

ええ何それ、というのが発端でした(後出し失礼)。

確かに、メインスレッドの終了時のこともありますし、スレッドの後始末をちゃんと
した方が本当はいいように思われます。処理が長時間たっても終了しない場合
タイムアウトさせたりとかも。
何かシステマティックな方法等あるでしょうか。参考になるものがあれば...

761 :はちみつ餃子 :2024/01/22(月) 12:54:36.50 ID:T1sqP3ZB.net
>>760
メインスレッドの終了直前でまずは適当にフラグを立てた上で他のスレッドの終了まで待機する。
重い処理をしているスレッドの側で完了ではないにしても区切り良く終われるポイントでフラグを読んで
フラグが立っていれば後始末ルートに入ってスレッドを終了させる。
その結果としてメインスレッドの待機状態が終わってプロセスの終了。
というのが普通の大まかな流れだと思う。

その上で待機時間があまり長すぎるようだと強引にでも終わらせるとかの処理を入れるかも。

std::async は既存の関数を非同期化するちょっとしたユーティリティという立場なんじゃないかな。
それで事足りるときは便利で簡単だけど、細かい制御を勝手にやってくれるわけでもないし、
やろうとするとちょっとイマイチって感じ。

762 :デフォルトの名無しさん:2024/01/28(日) 11:52:43.80 ID:W0uCnQb3.net
質問なのですがどんな環境(ロケール設定)のPCで動かしても
数値や時刻の入出力を修飾無し(12345 が 12,345 になったりしない)にする完璧な方法って次の3行で良い?
 setlocale(LC_ALL, "");     // printf()、scanf()に反映
 _wsetlocale(LC_ALL, L""); // wprintf()、wscanf()に反映 (※ 環境依存。左記はWindowsの場合
 std::locale::global(std::locale("", std::locale::all));  // cout、wcout、cin、wcin、ostringstream、wostringstream、...etc. C++の全部に反映

あとなんか実験する限り
 cout.imbue(std::locale(""));
 std::locale::global(std::locale("", std::locale::all));
とするとcoutが修飾有りとなり、cout.imbue()で与えた設定をstd::locale::global()が上書きしないように見えるのですがそういうもの?

763 :はちみつ餃子 :2024/01/28(日) 13:12:39.75 ID:hRRbWEE/.net
>>762
言語仕様通りならそれらの関数を呼び出さないようにすれば環境に固有の表現の変換はしない。

std::setlocale の設定が C の標準関数の挙動に影響するのはその通り。
ただし、様々な環境での「同じ動作」を期待するなら "C" を与えるべき。
空の文字列を渡した場合には環境に固有の設定であり、通常はシステムの設定が反映される。
プログラムは起動したときに setlocale(LC_ALL, "C"); 相当の状態なので、普通は書く必要もない。

std::locale::global での設定は C++ の標準ライブラリの挙動に影響するだけでなく std::setlocale での設定にも反映されるので両方を呼び出す必要はない。
これもプログラム起動時のロケール設定は "C" 相当になっているのでそれで良ければ呼び出す必要もない。
ただし、 std::locale::global に与える設定が名前を持たない場合 (つまり std::locale("") のような場合) は std::setlocale 相当の変更もするかどうかは規定されない。

imbue はストリームにロケールを結びつけるのでグローバル設定とは独立して機能する。

764 :デフォルトの名無しさん:2024/01/28(日) 14:11:55.68 ID:eBJAlicu.net
クラスオブジェクトの代入文に、=による単純コピーと、=演算子関数による独自コピーのどちらを使うか迷います。

たとえばメンバ変数が基本データ型の集まりなら単純コピーでいい。
今出くわしたのはメンバ変数がstd::array<int, 3>の場合で、まあたぶん単純コピーでよさそう?じゃあstd::vector<myclass>なら?などと疑問が深まります。

あとコピーコンストラクタによる初期化も合わせて考える必要がありそう。

765 :はちみつ餃子 :2024/01/28(日) 14:36:51.31 ID:hRRbWEE/.net
>>764
単純コピーってのは何のこと?
デフォルトで生成される代入演算子の意味で言ってるのかな?

766 :デフォルトの名無しさん:2024/01/28(日) 15:36:35.20 ID:W0uCnQb3.net
>>763
レス㌧クス、
>ただし、様々な環境での「同じ動作」を期待するなら "C" を与えるべき。
なるほど "C" ですたか、これか↓
https://www.ibm.com/docs/ja/zos/2.2.0?topic=utility-locale-naming-conventions

>普通は書く必要もない。
実はウィンドーズでUnicodeで出力する場合限定かもですだが、ロケール設定しないままだと
日本語OSでも漢字が表示されなかったり(L"Hello World! 漢字" → 表示: Hello World! )
英語OSに持っていったら L"Hello World! 漢字" が丸ごと出なかったり……orz
まあ漢字はこの際どうでも良いので、ロケール設定 "C" で行こうと思いまつ

767 :デフォルトの名無しさん:2024/01/28(日) 16:37:46.15 ID:eBJAlicu.net
>>765
そうです。

768 :はちみつ餃子 :2024/01/28(日) 16:38:46.52 ID:hRRbWEE/.net
>>766
Windows での話か……。
msvcrt だとどうにもならなくて ucrt でちょっとマシになってるみたいな話題をこないだ Teratail で見たぞ。

769 :はちみつ餃子 :2024/01/28(日) 16:52:54.16 ID:hRRbWEE/.net
>>767
デフォルトで生成される代入演算子は全てのサブオブジェクト (基底とデータメンバ) を
代入演算子でコピーするのと同じ挙動になることになってる。
基底やデータメンバが適切に代入演算子を定義されているのならデフォルト生成にまかせてよいことが多い。

注意を払う必要がある典型的なものは生ポインタで、
ポインタをコピーしても指してる先のオブジェクトはひとつだから
そのへんの扱いはデフォルト生成だとあかんことになる。

あとは外部のリソースと結びついているオブジェクトだと単純にコピーできないか、コピーさせないこともあるな。
分かりやすい例で言うなら std::thread なんかはスレッドを抽象化したものだけど
オブジェクトをコピーしたらスレッドもぽんぽん増えるなんてことになっても困るし
スレッドひとつに対応しているオブジェクトがいくつもあるようでも困るのでコピーできないようになってる。

それぞれに事情があるので明瞭な判断基準があるわけじゃないけど、
デフォルト生成の結果がほんまに自分の意図通りに動作するか考えてみて
あかんなら自分で書くしかない。

770 :デフォルトの名無しさん:2024/01/28(日) 17:03:17.17 ID:eBJAlicu.net
>>769
いつもありがとうございます。
たいていはデフォルトでよさそうですね。
std::vectorは可変長配列ってことなので、<int>であってもデフォルトでいいのかなと心配に…あこれはvectorのほうで独自=定義されてるなら問題ないわけですね。

771 :デフォルトの名無しさん:2024/01/30(火) 20:47:22.29 ID:RcbbllHt.net
bだけ通らないのが納得いかない…。

#include<iostream>
#include<functional>

using F = std::function<void()>;
void f0(){}
F f1;

class X {
F f;
public:
X(const F& f_) : f(f_){}
X& operator=(const F& f_){f = f_; return *this;}
};

int main(){
X x1(f0); // a:OK
X x2 = f0; // b:NG(conversion from ‘void()’ to non-scalar type ‘X’ requested)
X x3 = f1; // c:OK
x1 = f0; // d:OK
}

772 :はちみつ餃子 :2024/02/02(金) 00:09:46.55 ID:BQKaaqcl.net
>>771
std::function ではなくごく単純なクラスでもエラーを再現できる。
暗黙の変換は原則としては多段には起こらず、 X→Y, Y→Z な変換が可能なときでも X→Z な変換はしない。 (プリミティブな型変換とクラスの型変換が連鎖することはある。)
以下の例だと X x1(1); という宣言のときに必要な「暗黙の変換」は int から foo という一段のものだけど X x2 = 2; としたときに必要なのは int から X だから一段の変換ではできない。

struct foo {
foo(int x) {}
foo(const foo&) = default;
foo(void) = default;
};

foo f1;

class X {
foo f;

public:
X(const X&) = default;
X(const foo& f_) : f(f_) {}
X& operator=(const foo f_) {
f = f_;
return *this;
}
};

int main() {
X x1(1); // a:OK
X x2 = 2; // b:NG(conversion from 'int' to non-scalar type 'X' requested)
X x3 = f1; // c:OK
x1 = 3; // d:OK
}

773 :デフォルトの名無しさん:2024/02/02(金) 11:28:24.45 ID:xohFoxUO.net
>>772
横からだけども
> X x2 = 2; // b:NG(conversion from 'int' to non-scalar type 'X' requested)
って
X x2(2);
と同義じゃねーの?

774 :はちみつ餃子 :2024/02/02(金) 12:19:41.13 ID:BQKaaqcl.net
>>773
違うよ。
C++ では引数ひとつのコンストラクタは変換コンストラクタとして「も」使うことになっているから
違う文脈でも結果的に同じコンストラクタが呼び出されることになるけど
構文糖というわけではなくて違う解釈を経ている。

775 :デフォルトの名無しさん:2024/02/02(金) 12:28:48.56 ID:xohFoxUO.net
細かいなぁ

776 :はちみつ餃子 :2024/02/02(金) 18:32:30.30 ID:ZFQgO+dm.net
動くなら同義と考えても大した問題じゃないが、
ここでは実際に結果が違う (一方はエラーになる) ことの説明だから……

777 :デフォルトの名無しさん:2024/02/02(金) 22:30:30.14 ID:d8Flt8Cn.net
これはなぜエラーになるのですか。
std::string s = "abc";
char name[10] = s.c_str();

error: array must be initialized with a brace-enclosed initializer


次と同等とみなせないのはなぜ?
char name[10] = "abc";

778 :774:2024/02/03(土) 05:00:19.85 ID:vGyzbOvf.net
>>772 774だけどありがとう。暗黙だと変換が途中で途切れるかもなのか。
一番通って欲しいのがbなんだけど難しいっすね…

779 :デフォルトの名無しさん:2024/02/03(土) 05:21:33.46 ID:4Ieoi/Xm.net
>>777
c_str()が返すのはchar*
char name[10] = "abc"; は特別扱いで char name[10] = {'a', 'b', 'c', 0}; と同じ
cの時からある雀の涙猫の額ばかりの文字列サポート

780 :はちみつ餃子 ◆8X2XSCHEME :2024/02/03(土) 08:35:44.53 ID:Sz70frqK.net
>>778
少し表現を変えて良ければ >>771 の X x2 = f0; を
X x2 = {f0}; と書くことでも通すことは出来るよ。

更に真面目に対処するならこんな感じかな。
https://wandbox.org/permlink/giXZnCETo64IkEez

781 :デフォルトの名無しさん:2024/02/03(土) 22:40:06.88 ID:mzdZy5dk.net
>>779
あーそういうことですね。ありがとう。

782 :774:2024/02/04(日) 02:54:38.53 ID:1VXaeA8L.net
>>780 上は={}で通るのは確認してました。{}付けるとX型に見なされてコピーコンストラクタで初期化されるで合ってますか?
下の方、typenameの所は余りよく分からなかったですが強制的に引数の型で包んで(オブジェクト生成?)、コンストラクタの引数代入時に変換追加するということでいいですか?
typename以下はdecltype(f_)((f_))でも良いんかなと思って変更してみたら通りました

783 :はちみつ餃子 :2024/02/04(日) 09:54:01.38 ID:/H29LerN.net
>>782
> {}付けるとX型に見なされてコピーコンストラクタで初期化されるで合ってますか?

いいえ。 直接初期化に該当します。
コピー (コピーコンストラクタの起動) は発生しません。
つまり X x1(f0); と書いた場合と同じということです。
ですから暗黙の変換を一段階すれば充分なのでエラーなく通ります。

> コンストラクタの引数代入時に変換追加するということでいいですか?

いいえ。 何もしません。
コンパイルを通すためには不要ですので、 X のコンストラクタは

template <class T>
X(const T& f_) : f(f_) {}

という定義だけでも問題なく動作します。

ただ、こうすると T は「あらゆる型」になりえます。
std::function<void()> に変換不可能な型も受け入れてしまうということです。
変換不可能であればいずれにしても最終的にはエラーなのですが、
X がデタラメな型も受け入れてから F に変換失敗してエラーになるよりは
特定の条件を満たす型以外を X が拒否するほうが一般的には都合がよいので
そうなるようにしたのです。

コンパイルを通すために必要なのではなく通さないための処置です。

784 :774:2024/02/04(日) 22:33:14.16 ID:1VXaeA8L.net
>>783 上:初期化周りは似たような物が色々あって知識が曖昧でした。
下:あの記述は型制限の為ですか。読んでも意図がよく分からなかったので助かります。
説明ありがとうございました

785 :デフォルトの名無しさん:2024/02/10(土) 13:14:08.12 ID:KJGevrBa.net
質問なのですがstd::coutに対する
 (a) 固定小数点表示
 (b) 小数以下精度指定(例えば20桁
 (c) setw()される表示幅に対し足りない上位桁0埋め
という表示仕様への変更と復旧は、変更が
 auto sv_flags = cout.flags(); cout << std::fixed; // (1)
 auto sv_prec = cout.precision(std::streamsize(20)); // (2)
 auto sv_fill = cout.fill(); cout << std::setfill('0'); // (3)
復旧が
 cout.flags(sv_flags); // (1)の変更から復旧
 cout.precision(sv_prec); // (2)の変更から復旧
 cout << setfill(sv_fill); // (3)の変更から復旧
と書くのが普通?シグネチャが不統一な印象があるますがもっとズバっとやる方法は無いもの?
((1)は変更にcoutのメソッドとマニピュレータが両方要り、復旧はcoutのメソッド。
 (2)は変更も復旧もcoutのメソッドで済む。(3)は変更が(1)と同じパティーンで復旧がマニピュレータ……

786 :はちみつ餃子 :2024/02/10(土) 14:30:14.27 ID:XEL9SE6k.net
>>785
・ 直接的に入出力を司るのはバッファと呼ばれるオブジェクト
  (たとえば basic_streambuf など)
・ ストリームには対応するバッファがセットされている (あまりバッファを直接には操作しない)
・ 書式はストリームの状態として保持されている

つまり同じバッファ (出力先) に対して異なるストリームをかぶせることが出来る。
一時的にだけ書式を変更するのであれば一時的なストリームを作るという方法がとれる。
コードで例を出すならこんな感じ。

#include <iostream>

int main() {
std::cout << 0.1 << std::endl;
{
std::ostream temp(std::cout.rdbuf());
temp.precision(30);
temp << 0.2 << std::endl;
temp << 0.3 << std::endl;
}
std::cout << 0.4 << std::endl;
}

書式をストリームの状態として持つのがすこぶる不格好だというのは
C++er にとっての共通認識になっていてようやく C++23 から std::print が導入されたので
モダンな C++ を使えるならそっちを使ったほうが良い。
std::format なら C++20 から。

787 :デフォルトの名無しさん:2024/02/10(土) 15:00:10.91 ID:KJGevrBa.net
>>786
㌧クスなるほど……
変更した書式の戻し忘れが無く、問題らしい問題点はほぼ無しで良さげ……
(しいて言えばstreamの中の作りを理解していなければtempが何の目的でそうするのかわかりにくい(コメント必須)なだけ、

std::printは手元のVC++がまだC++20対応止まりなので当面見送らざるおえない

std::formatは…… 書式文字列が定数式限定という仕様のはいかがなものか……
今回の用途では困りませんし、コンパイル時に書式の妥当性をチェックしてくれるのは良いのですだが、
仮に、C言語における自作printf()様インターフェースの関数(書式文字列と可変長引数を変数で受け取り、内部でvprintf()を呼ぶ)
みたいなものを作りたくなった場合どうするんじゃとそこはかとなく疑問が……

788 :はちみつ餃子 :2024/02/10(土) 15:16:22.24 ID:XEL9SE6k.net
>>787
実行時バージョンとして std::vformat も用意されている。

789 :デフォルトの名無しさん:2024/02/10(土) 15:25:38.54 ID:KJGevrBa.net
>>788
なるほどなるほど、自作std::format()様関数は問題無く作成でき、
書式文字列が定数式限定が困るというのは杞憂ですたねサーセン;;;
(実行時にならないと書式文字列が決まらない場合、コンパイル時チェックが原理的に不可能になるのはC言語のprintf()/vprintf()の関係も同じなのでC言語からの後退ではない

790 :はちみつ餃子 :2024/02/10(土) 16:29:24.58 ID:XEL9SE6k.net
メンバとして copyfmt があって、これで書式を他のストリームにコピーすることも出来る。
書式を待避しておくだけのストリームを作ってそれにコピーしておいて
後で元に戻すという使い方をしてもいいんだけど、
どうせストリームをあらたに作るならそれを一時的なストリームとして使ったほうが自然かと思う。

791 :デフォルトの名無しさん:2024/02/11(日) 22:38:22.35 ID:smEWrSvv.net
std::setのinsertで

std::set<int> c1 = {1,2,3};
std::set<int> c2;

c2.insert(c1);

と書けると便利に思えますが解説のページを見るとできないようです。
なぜですか。

792 :デフォルトの名無しさん:2024/02/11(日) 22:45:16.04 ID:KNbj1ANO.net
>>791
c2.insert(c1.begin (), c1.end ());

793 :はちみつ餃子 ◆8X2XSCHEME :2024/02/12(月) 11:50:11.55 ID:4VueJhli.net
>>791
set に set を insert できる「だけ」ってのはあまり便利ではない。
集合というものをより汎用的に扱える枠組みとして C++20 から range という概念が導入された。
その枠組みを上手いこと成立させる言語機能 concept が長いこと検討されてて、
入る入ると言いながら C++20 までずれ込んでしまったという事情がある。

そんなわけで、 C++23 からなら insert_range が使えて、
これは range の条件を満たすものならなんでも受け入れられることになってる。

794 :デフォルトの名無しさん:2024/02/12(月) 21:37:56.53 ID:WngRm50l.net
>>791
c2.merge(c1) ※C++17以降

795 :デフォルトの名無しさん:2024/02/13(火) 22:11:49.56 ID:TA8E1xmn.net
みなさんありがとう。環境適合を優先して>>792を使うことにします。

796 :デフォルトの名無しさん:2024/02/18(日) 00:05:28.51 ID:AtsZxBPF.net
コンストラクタの初期化子リストの中で、どこまで柔軟に記述できるのかなーと思ってGPT先生に聞いたら、constまたはconstexprを返す関数のみ書けるとのことでした。
コンストラクタ内部のように好きなように書けないとわかり、初期化子リストの価値が低く感じられました。

そんな制限を設けてまで初期化子リストを導入した意図は何でしょう。

797 :デフォルトの名無しさん:2024/02/18(日) 01:13:17.69 ID:UTNyRtZE.net
ChatGPTなんかあてにするな、平気で間違ったこと言うんだから
constやconstexpr以外を返す関数だって普通に呼べる

試しにChatGPTに「メンバ初期化子リストではconstかconstexprを返す関数しか呼べませんが、これはなぜですか?」ってあえて間違った前提条件で質問してみたら、間違ってることに対する指摘は一切なかったし、さもこっちの質問が正しいかのようなそれっぽい返答が返ってきたし

---
俺:
C++において、コンストラクタのメンバ初期化子リスト内ではconstまたはconstexprを返す関数しか呼ぶことができません。これはなぜでしょうか?

ChatGPT:
C++において、コンストラクタのメンバ初期化子リスト内でconstまたはconstexprを返す関数しか呼ぶことができる理由は、初期化子リストがオブジェクトの初期化に使用され、実行時のコードが生成されないためです。メンバ初期化子リストはコンストラクタの一部であり、オブジェクトが生成される際に実行されます。このリスト内での関数呼び出しはコンパイル時に解決され、オブジェクトの初期化に関する情報は実行時に生成されません。

constまたはconstexprを返さない関数をメンバ初期化子リスト内で呼ぶと、実行時にコードが生成される可能性があります。しかし、これはオブジェクトが生成される前に行われる初期化の一環であり、実行時の処理としては不要なオーバーヘッドを引き起こす可能性があります。

コンストラクタのメンバ初期化子リストは、メンバ変数を適切に初期化するためのものであり、できるだけ効率的に行われるように設計されています。そのため、コンパイル時に解決されるconstまたはconstexprを返す関数の呼び出しに限定されています。
---

だからAIをあてにしちゃダメだよ

798 :デフォルトの名無しさん:2024/02/19(月) 00:17:49.94 ID:bJlSKdBs.net
>>797
私が聞いたときも似たような内容が含まれていて、そうなんだねと納得してしまいました。

ではコンストラクタに書けることはすべて書けるのですね。

なおこの問いは、入門書籍にはそこまで書かれてなくて、検索でもかんたんに見つからなかったので聞きました。

799 :はちみつ餃子 :2024/02/19(月) 02:33:45.03 ID:j7eyydGe.net
>>798
たぶん >>796 で言う「初期化子リスト」は「メンバ初期化子リスト」だよね?
これらは全くの別物。
明らかに混同しやすい用語だから仕方がない部分はあるんだが、
誤った用語を元に調べたら誤った解説に当たりやすいかもしれない。

メンバ初期化子リストは直接初期化 (direct-initialization) であると規定されていて
具体的な挙動の説明は初期化の章に丸投げされている。
https://timsong-cpp.github.io/cppwp/n3337/class.base.init#7
つまりメンバ初期化子リストに特有の事情というものはない。

普通に初期化なんで、そこに違いがあるかもしれないという想像をする人がいてそういう人のために
違いが無いと断りを入れる必要があるとは入門書の著者は思わなかったんだろう。
有るものを有ると説明することはあるが無いものを無いと殊更に強調して説明はあまりしない。

800 :デフォルトの名無しさん:2024/02/19(月) 22:58:00.95 ID:bJlSKdBs.net
>>799
そうですメンバ初期化子リストです。どうもありがとう。
なお書籍には、メンバ変数名(引数)やメンバ変数名(0)の例ばかりでした。

801 :デフォルトの名無しさん:2024/02/26(月) 09:17:00.78 ID:KZUiymUx.net
すみません、コンストラクタの宣言/定義で A() {}; とした場合と A() = default; と
書いた場合は何が違うのでしょうか。挙動とか意味だとか...
あるいはある種のタイプクラスの場合は違いが生じるので注意とか....??

802 :はちみつ餃子 :2024/02/26(月) 09:36:14.06 ID:pFLZLcAJ.net
>>801
default を指定した場合はデフォルトのルールでコンストラクタを生成する。
生成可能な条件が満たされなかった場合でもそれ自体はエラーにはならずに
デフォルトコンストラクタは削除済と見做されるというルール。

そのときはデフォルトコンストラクタを必要とする使い方をした時点でエラーになる。

803 :はちみつ餃子 :2024/02/26(月) 09:39:35.86 ID:pFLZLcAJ.net
つまりこんなことをしてもエラーは出ないが

struct foo {
foo() = delete; // デフォルトコンストラクタを削除
};

struct bar : foo {
bar() = default; // デフォルトコンストラクタのデフォルト生成
};

int main(void) {
}

↓ こういうことをするとエラー

struct foo {
foo() = delete; // デフォルトコンストラクタを削除
};

struct bar : foo {
bar(){}
};

int main(void) {
}

804 :デフォルトの名無しさん:2024/03/02(土) 19:28:56.45 ID:fBQwxymt.net
>>803
遅レスすみません。要は、コンストラクタの特定のパターンの用法をされたくない
ときに使う感じ? でそれに該当するとコンパイルエラーになるわけですよね?

自分が気になったのは、ランタイム時に何かありうるかということです
あるコードで、コンストラクタがdefault指定されているクラスが、別のクラス内
(親子関係にはない)でunique_ptrとして生成されたときに問題が生じたような
感じで....
ってもっと自分で調べてからレスしろって話ですが、現在そのコードに立ち戻る
ことができず、とりあえず疑問だけを

805 :はちみつ餃子 ◆8X2XSCHEME :2024/03/02(土) 21:07:53.65 ID:JOojncXx.net
C++ の仕様は場合分けで規則がごちゃごちゃしていることが多くて単純な一般原則として説明できない。
「要は」なんて一言でまとめられないよ。

806 :デフォルトの名無しさん:2024/03/03(日) 19:37:10.80 ID:HNPAS3Wj.net
>>804
そういう目的ではないと見ていいよ
>>803が言ってるのは、基本的にはデフォルト実装でコンストラクタを作ってくれるが必ずではない、と言ってるだけ
デフォルトの(引数無しの場合、何もしない。が、基底クラスの引数無しのコンストラクタはちゃんと呼んでくれる)コンストラクタでいい場合に使う。

A() {}と書くのと基本同じだよ

807 :デフォルトの名無しさん:2024/03/12(火) 20:26:30.54 ID:lzPsc8Dg.net
異なる型を含むような配列(的なもの)を作りたいのですが、可能でしょうか?
例えば template <T> struct NamedValue { string name; T value; } を定義して
NamedValue<string>{a, b} や NamedValue<int>{c, d} などの型の異なる複数の値を、
一つの配列的なものに収納したいのです
例えばvectorは全要素が同じ型じゃないと駄目ですよね

808 :デフォルトの名無しさん:2024/03/12(火) 21:14:27.11 ID:irRbCjS4.net
>>807
std::tuple

809 :デフォルトの名無しさん:2024/03/12(火) 21:19:48.50 ID:irRbCjS4.net
あるいは要素数がコンパイル時に決まらないなら
std::anyをコンテナに入れるとか?

810 :デフォルトの名無しさん:2024/03/12(火) 22:11:10.08 ID:lzPsc8Dg.net
はい、要素数はコンパイル時に決まらないのでstd::anyのコンテナですかね
で要素を取り出すときは、どの型なのかをチェックして挙動を...

811 :はちみつ餃子 :2024/03/12(火) 23:03:39.03 ID:WtXn1sYk.net
もし >>807 の T の種類が限られているのなら std::variant を使ったほうが楽かもしれない。
std::visit を使えば型の種類ごとに処理を切り替えるのが便利なことがある。

812 :デフォルトの名無しさん:2024/03/23(土) 11:43:27.62 ID:YZ3MX9tD.net
std::remove()ってファイルを消去する関数なんですね
std::move()と名前が似ているのに全然違う

813 :デフォルトの名無しさん:2024/03/23(土) 12:38:58.15 ID:6dCwgWlj.net
名前空間か関数名にfileくらい入れとけって思うよね

814 :デフォルトの名無しさん:2024/03/23(土) 12:50:26.95 ID:epZulncV.net
C言語以前にE言語の問題や
さすがにそのくらいの英語の勉強はしておけと思う

815 :はちみつ餃子 :2024/03/23(土) 12:51:15.85 ID:szITgpvT.net
C の規格から取り込んだものだから由来が違うんだよ。
今なら std::filesystem::remove があるからこちらを使うほうが良い作法だと思う。

816 :デフォルトの名無しさん:2024/03/23(土) 12:54:13.64 ID:aQWBK6SI.net
>>812
>std::remove()ってファイルを消去する関数なんですね
std::remove()ってSTLのstd::removeじゃなく?
ちゃんとコンテナの要素をre-moveしてると思うが?

817 :デフォルトの名無しさん:2024/03/23(土) 13:38:01.48 ID:qgcdIGgP.net
>>816
だよねえ??

>>812-815が何を言ってるのか分からなくて怖い

818 :デフォルトの名無しさん:2024/03/23(土) 13:40:27.68 ID:qgcdIGgP.net
ああ
<cstdio>に
int remove( const char* pathname );
ってのがあるのか
https://en.cppreference.com/w/cpp/io/c/remove

819 :デフォルトの名無しさん:2024/03/24(日) 05:14:16.83 ID:DBUI72Gl.net
>>815
なるほど。諸般の事情でC++14な環境で、ファイルを扱う関数を探していたら。
Boostに行く手もあるかもしれませんが、とりあえず。

820 :デフォルトの名無しさん:2024/03/24(日) 09:50:29.58 ID:FsPOi81N.net
cstdio のは std:: 名前空間じゃないよね.
::remove だと思うけど

821 :はちみつ餃子 :2024/03/24(日) 12:13:25.60 ID:iaJ2USO3.net
>>820
cstdio にある関数は std 名前空間にある。
ただしグローバル名前空間「にも」あって良い。 (無くても良い。)
stdio.h の場合はグローバル名前空間で宣言されるが std 「にも」あってよい。 (無くても良い。)

822 :デフォルトの名無しさん:2024/04/14(日) 11:55:59.92 ID:Rac57Bvn.net
ヒエッ……、、、ぎ、玉虫色……

823 :デフォルトの名無しさん:2024/04/20(土) 14:55:18.13 ID:nh5GJjX6.net
言語そのものではないのですが、コマンドラインのデバッガやIDEでSTLのコンテナの内容を
易しく表示してくれるのってありますか?
例えばvectorなら、単純に中の要素だけを列挙してくれたりとか

ビルドにCMakeを使っているのでとりあえずCLionを使っていますが、これは
確かに変数の中身をリスト構造で見れますが、変数内の生のメンバー(M_なんちゃら等)
見えてる感じで、STLコンテナに関してはあまり親切ではないような
デバッグの際は見えた方がいい場合もあるのでしょうが。なら表示が切り替えられたりとか?
自分はmacOSですが、他のプラットフォームにしかないものも参考に聞いてみたいです

824 :デフォルトの名無しさん:2024/04/26(金) 10:53:44.71 ID:kftlKAnq.net
今からC++を勉強するならC++20を基準にやっても構いませんか?

825 :デフォルトの名無しさん:2024/04/26(金) 10:59:40.04 ID:/+TxHGye.net
c++20といわずc++23からやればいいのでは

826 :デフォルトの名無しさん:2024/04/26(金) 11:15:59.06 ID:kftlKAnq.net
最新の規格で勉強して必要に応じて古い知識をつけていくような学び方でいいの?

827 :デフォルトの名無しさん:2024/04/26(金) 12:03:42.74 ID:q/vvVdAs.net
つべこべ言わずやれ
最短コースなんてない

828 :デフォルトの名無しさん:2024/04/26(金) 13:37:23.03 ID:+usxQk3U.net
C++ は基礎の上に段階的に応用が乗っかっているような綺麗な構成ではない。
全部が入り組んで捏ねまわされてグダグダや。 そんでもってクソ巨大やねん。
どこから入っても同じ。

829 :デフォルトの名無しさん:2024/04/27(土) 18:08:12.52 ID:nxPk0zOn.net
質問なのですが
std::string には std::to_string(int)他の簡単文字列化関数がありますが
std::basic_string<T> に対する簡単文字列化関数はどう?

830 :デフォルトの名無しさん:2024/04/27(土) 21:15:22.77 ID:Zg+tfmdX.net
>>823
WindowsのVisual Studioではできる

831 :デフォルトの名無しさん:2024/04/28(日) 10:47:20.65 ID:xKAeYuwJ.net
最初に学ぶ言語がC++なら、Cより学ぶのが大変じゃん

832 :832:2024/05/11(土) 19:13:43.45 ID:RotYKdRC.net
やっぱ数値からstd::basic_string<T>の文字列への変換とかTが決まらないとやり方がわからないから
std::basic_string<T>でそれをやりたい人が対応せよ(std::basic_string<T>版to_string()やstd::ostrstreamをT毎に作成せよ)という天の啓示?
証拠にstd::wstringについてはstd::wstring to_wstring(int)とかstd::wostrstream とかある

833 :デフォルトの名無しさん:2024/05/13(月) 23:37:45.97 ID:E3c8DTgZ.net
>>832
分かっとるやないか

834 :デフォルトの名無しさん:2024/05/17(金) 02:48:48.77 ID:5PkVcelB.net
OS上で動かすアプリ作りたくなったからC++とC#で悩んだんだけどどちらの長所も捨てがたい気がして両方学んでみるかな?って思ったんだけどC++でのおすすめの参考書とかあります?
一応、学生時代にC言語で五目並べとファイルの出力までは勉強してます。
一応ググって入門参考書とか調べましたがちょっとC言語齧ったのなら実戦的な例題集みたいなのが良いのでしょうか?
あとこの質問スレ違いだったらすいません。

835 :デフォルトの名無しさん:2024/05/17(金) 09:33:44.70 ID:7hVV19/y.net
Windows上のアプリをC++で作るのは少々ハードル高いが
個人的にオススメなのはWindows2000 プログラミング標準講座(ハーバート・シルト著)ってやつ

C++そのものの本は他の人が挙げてくれると思う

836 :はちみつ餃子 :2024/05/19(日) 01:34:46.93 ID:lh74nkjR.net
どういう学び方が良いかは人による。
C++ の設計思想としては理解できた便利機能をその都度に導入する形で学んでいけるようにという配慮はしていると設計者は言っている。 実務でプログラミングをしてる人は「C++ をちゃんと習得するまで待ってくれ。 仕事を止めてくれ」とは言えないからね。 C を理解しているならとりあえず C のように書きながら部分的に C++ 的にしていける。
つまり実戦的な学びかたも一応はアリ。

ただ、実戦的な学習はやりたいことが出来てるならそれ以上深掘りする意欲につながらない。
C の書き方でやれるなら別の形に積極的に書き直したい理由って何?と感じてしまうことがある。
きちんとした理解に至らぬままの中途半端な形になりがち。

やりたいこと (書きたいもの) が明白なほうが道筋は付けやすいんだけど、やりたいことに邁進しすぎてもそれはそれで「学習」としてはイマイチなんだよ。
そのへんは程度問題というか匙加減というか、人による、場合によるとしか言いようがない。

個人的にはしっかりとした理屈っぽい入門書を一冊は読んでから方針を決めればいいと思ってる。

837 :デフォルトの名無しさん:2024/05/19(日) 14:09:52.90 ID:y+g7UiM3.net
>>835
レス、ありがとうございます
Windows2000 プログラミング標準講座が近所の図書館にもなかったのでそこにある蔵書読んでみてVisual studio使ったプログラミングしたことないからそれをツールとして使った入門書でいいかな?って思ってしまいました。
>>836
レス、ありがとうございま。。
何を作りたいかの方向性でそれに使うものだけ勉強すれば速いというのはわかります。
自分的には作りたいアプリもあるけどまずGUIアプリを作るための基礎からやりたいなと思ってます。
理屈っぽい入門書の理屈っていう部分はプログラムのハードでの処理の考えとかかと思ったのですがそれはたぶん理工系の学部行ってたので通信情報の基礎理論は聞いたことあるので大丈夫だと思います。
C++は基礎わかってれば後は組み込みたい機能のコードを探せばいいってことと解釈してコード集みたいな辞典を使ったり、ネットで調べたりすればいいってことでいいのでしょうか?

838 :はちみつ餃子 ◆8X2XSCHEME :2024/05/19(日) 15:08:47.80 ID:lh74nkjR.net
>>837
私がいう「理屈」は言語仕様のことのつもりで言ってた。
低レイヤから入った C ユーザーは C を使えているようでも言語仕様に対する理解が浅くなりがちで、
良くも悪くも機械語 (ハードウェアの挙動) と対応づけて考えてしまうところがある。
言語としての抽象とその実装は分けて考えないといけない。

現代的なコンパイラは最適化がメチャクソに賢いので実際に生成される機械語と一対一には対応づかないし、
言語仕様で未定義としているところを踏んだらわけのわからない動作を引き起こすので
言語仕様について一定以上には身に付けてから実践を始めないと何がなんだかわからないことだらけだと思う。

逆に一定以上に C++ の基礎を身に付けてからならあとはリファレンスを見ながらでも行けるけれど、
今の C++ の「基礎」は昔の C++ と比べるとかなり巨大になってしまっているので当初の C++ の設計思想のように
C から段階的に C++ を身に付けるってのはあまりお勧めできないと私は考えてる。
C++ はとにもかくにも巨大で言語機能はお互いに絡み合っているので部分ごとの理解なんて出来ないんじゃないかということ。

繰り返すけど、人による。
自分なりにどういう方向性で行ったらいいのか判断するためにはどこからでもいいから一旦は始めたらいい。
どうせまったく躓きなく進むなんて出来ないんだから駄目だったときにどこが駄目だったかを検討して
軌道修正するしかしょうがないんじゃないのかな。

839 :デフォルトの名無しさん:2024/05/19(日) 15:25:20.86 ID:TV8v+5zc.net
>>837
一応Amazonで中古が出てる

最近の本を知らないのでなんとも言えんのだけど、
Visual Studioと名のつく本は、開発環境(VisualStudio)依存の機能使いまくりで他で応用が効かないんだわ、本を選ぶときの参考にしてくれ
(開発環境に依存しまくりでいいなら、ぶっちゃけC#のがはるかに楽)

>>835はWin32APIやメッセージループとかの「ずっと変わらない基本」をちゃんと教えてくれる本として挙げた

840 :デフォルトの名無しさん:2024/05/19(日) 19:24:07.63 ID:y+g7UiM3.net
>>838
言語仕様ですか
私自身、自分はハードを動かすためにCやアセンブラ触った口だから多分それに該当しそうです。

>>839
ちょっと気になったのですがハーバート シルト(著)の標準講座C++とか独習はどうなのでしょうか?
ハーバート・シルト氏の著書を少々調べてみたのですがどれも人によっては難しいとコメントあるけど素晴らしい学習書という人が多いみたいでしたので

841 :はちみつ餃子 :2024/05/19(日) 20:21:36.73 ID:lh74nkjR.net
>>840
C++ の仕様は不変なわけではなくてたまに改定してるというのは考慮に入れる必要がある。
どの仕様かを言うときには改定年度を付けて表す通例があって、現時点では C++98, C++03, C++11, C++14, C++17, C++20, C++23 がある。

入門レベルなら最新を積極的に追うほどの必要はないけど、最低限度は C++11 だと思う。
改定の期間があいたせいでインパクトの大きい変化があった。
それより古い書籍は良書だとしても現状に合わないところは色々とあるかもしれない。

GCC や Clang は特に指定しなければ C++17 モードのようなので現時点の基本は C++17 くらいというのが一般的な認識なんじゃないかな。

842 :デフォルトの名無しさん:2024/05/19(日) 21:02:45.49 ID:TV8v+5zc.net
あーそういや独習書いた人だっけ
独習は定番レベルで評価高い、ある程度Cの知識は前提になるけど読めると思う
C++標準講座は読んだことないのでわからんすまん

843 :1:2024/05/29(水) 05:15:45.12 ID:fgEqna2o.net
なに?プログラムって。むつかしそうだなー
ぜんぜん知らないんだけど、ちょっとやってみたいなー

ってな人も、入れてあげてね。
そういうスレなんだから。

844 :デフォルトの名無しさん:2024/06/11(火) 02:11:04.90 ID:T9Og4Yet.net
質問です。
独習でc++勉強してるのですが掛け算して出力するっていう練習問題見ててふと気づいたのですがこの本一体どの文字コードで保存すること考えて書いてるんだ?っていう疑問が出てきました。
sjisだとちゃんと日本語表示されるけど汎用性ないよな?ってことでUnicodeで書くこと前提で勉強したほうがいいよなって思ったんですが下のコードだと何を直せばいいのでしょうか?


#include <iostream>
using namespace std;

int main()
{
double hours, wage;

cout << "労働時間を入力する: ";
cin >> hours;

cout << "時給を入力する: ";
cin >> wage;

cout << "合計賃金は" << wage * hours << "円\n";

return 0;
}

845 :はちみつ餃子 :2024/06/11(火) 05:44:39.09 ID:oZDOZRBo.net
>>844
データの型としては unicode を扱えるようになってるけどコンソールは言語の外の話なので Unicode を扱えるかどうか、使えるにしてもどう切り替えるのかは言語仕様としては決まってない。
Unicode で出力は出来るけどそれを理解して表示できる環境かどうかはわからないということ。

846 :デフォルトの名無しさん:2024/06/11(火) 10:47:36.44 ID:GrH0S5VC.net
実行環境を変える
setlocale()するとか

847 :デフォルトの名無しさん:2024/06/11(火) 15:21:46.44 ID:T9Og4Yet.net
>>844
つまり、自分のところの文字エンコード使えってことでしょうか?
動作的には目的通りできますし、環境次第で文字表示はどれ使えるか変わってくるしで

>>846
実行環境はこの環境で使えるプログラム組めるまで気長にやるつもりなのでなしです。
setlocale()使ったことないのでよくわからないのですがロケール宣言してその中で日本語使ってみたらってことですか?

848 :デフォルトの名無しさん:2024/06/11(火) 16:20:37.40 ID:ILw6YbJs.net
長らくVS触ってなかったんであまり役に立たんかもしれんけど
・Visual Studioでutf-8でソース書く方法
http://tech.hikware.com/article/20171020a.html

・Win32APIをutf-8で使う
https://learn.microsoft.com/ja-jp/windows/apps/design/globalizing/use-utf8-code-page

C++標準ライブラリに関してはロケール設定でいけるんじゃなかったっけ、違ってたらすまん

849 :デフォルトの名無しさん:2024/06/11(火) 16:33:04.86 ID:ILw6YbJs.net
https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=msvc-170
下の方にsetlocaleでutf-8指定する方法書いてる
で、ソースコードもロケールもutf-8になってりゃ>>844のコードそのままでutf-8で実行してくれるはずよ

850 :デフォルトの名無しさん:2024/06/11(火) 16:50:13.04 ID:ILw6YbJs.net
https://learn.microsoft.com/ja-jp/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-170
すまん、実行時もソースコードもオプションに/utf-8入れるだけだったわ
setlocaleしなくていい

utf-16にしたいんだったらまた別だけど

851 :はちみつ餃子 :2024/06/11(火) 17:31:31.68 ID:kKWOd8Cb.net
>>847
言語仕様には書いていないことだから実行環境 (OS やターミナル) のドキュメントを読んでねってこと。
色々な文字コードをサポートしていることもあるししてないこともある。
切り替えることが出来ることもあれば出来ないこともある。

それとストリームはリダイレクト (接続先の変更) される可能性がある。
やりたいことによっては
標準出力がターミナルに繋がっているときとファイルに繋がっているときを区別しなきゃならないかもしれない。

Unix 系 OS の場合はテキストを表示するのはターミナルで、ターミナルはごく普通のアプリケーションのひとつ。
OS 自体はアプリケーションとターミナルの仲立ちをしてるだけなんだけど……。

Windows の場合は標準のテキスト画面 (コンソール) は Windows に標準的に備わった特別なもの。
その特別なテキスト画面を使ってる間は Windows のドキュメントに書いてある通りにすればいいのだけど
Windows で別のターミナルを使うときはその制御方法の規格が確立してないから
主要なターミナルを判定して場当たり的な処理をしているのが現状。
近年は ConPTY という規格が使われ始めてるけどどんなターミナルもそれをサポートしているってわけではないから
結局は場当たり的に対処すべき対象が一個増えただけって感じ。 (将来的には統一されるといいなぁ……)

更に Windows は C ランタイムサポートが文字コード変換の機能も持っていて接続先を勝手に判定して
変換することがあって、その挙動がかなりわけがわからない。

色々あるけどまとめると「こうすればいい」という簡単な説明が出来ない入り組んだ事情があるって話。

852 :デフォルトの名無しさん:2024/06/11(火) 22:55:22.54 ID:T9Og4Yet.net
すいません。
私の環境ただ単にUTFが使用可能になってなかっただけでした。

853 :デフォルトの名無しさん:2024/06/12(水) 16:16:19.83 ID:HDPWhZcO.net
termcap/terminfoとか
init.d
inittab
getty

854 :デフォルトの名無しさん:2024/06/13(木) 02:54:21.20 ID:PAaiBuyr.net
人間に匹敵する知能を持った汎用人工知能を開発した研究者に総額100万ドルの賞金を授与するコンテスト「ARC Prize」が開催

855 :デフォルトの名無しさん:2024/06/15(土) 17:34:41.45 ID:kg6WNOQa.net
>>844

C++は、日本語対応していないよ、注意してね。
だから、"あいうえお"なんかのコードは実行されない。
俺はこれを理解するのに10年以上かかった。

856 :はちみつ餃子 ◆8X2XSCHEME :2024/06/15(土) 19:41:12.56 ID:g9ixUcaw.net
>>855
No.
現在は Unicode についての規定はあるし、 Unicode のコードポイントに対応つくことが保証された文字列リテラルはある。

857 :858:2024/06/15(土) 21:31:29.30 ID:kg6WNOQa.net
俺のエディタは、EmEditor Professional (64-bit)だ。
だ。だからC++は、C++17だ。
わからなかった。ごめんな。

858 :デフォルトの名無しさん:2024/06/16(日) 00:50:11.77 ID:v0fD0nKy.net
C++と文字コードに関してはこの記事が面白かった
https://qiita.com/yumetodo/items/54e1a8230dbf513ea85b
俺もあまり詳しくはないから全部理解できた訳じゃないけど、筆者の人がブチギレまくってるのを感じ取るだけでも面白かった

859 :デフォルトの名無しさん:2024/06/16(日) 23:06:40.05 ID:+HL215mo.net
>>854
どうやってチューリングテストするんじゃ……

860 :デフォルトの名無しさん:2024/06/16(日) 23:21:48.48 ID:+HL215mo.net
coutやcinとかなiostream系の入出力手段のうちのワイド文字でないやつは
エスケープ文字('\\'とか)や書式指定文字('%'とか)に依存しないから
つまりたまたまマルチバイト文字の一部が '\\' や '%' に一致してもなんら実害が無いから
Shift JISの入出力が問題を引き起こすことは無いという認識でおk?

861 :はちみつ餃子 ◆8X2XSCHEME :2024/06/16(日) 23:45:30.66 ID:Crm/SwBu.net
>>860
言語仕様的にはテキストモードでは実行環境の都合で各種の変換を入れても良い。 (入れなくても良い)
実際に Windows では文字コードや改行コードの変換をする。
改行が \r\n であるようなテキストを読んでも内部的には \n であるように扱えたりしてるのを不思議に思ったことない?
変換するということは変換元が想定通りじゃないときには破綻する可能性がある。
Shift JIS を使う設定にしてないときに Shift JIS を渡したら駄目かもね。

バイナリモードではバイト列そのまま。

Linux だとテキストモードとバイナリモードは区別がない。

862 :デフォルトの名無しさん:2024/06/17(月) 00:54:42.78 ID:pXzMaPAe.net
>>861
だいたいわかりた、
>実際に Windows では文字コードや改行コードの変換をする。
テキストモードにおける '\n' <--> '\r\n' 変換をやるだけでも、
cout << "アイウエオカキクケコ\nさしすせそ" << endl;
と書かれたうちの '\n' と endl の2箇所だけ正確に変換するためには、
上記1行の中に暗黙に含まれるSI/SOおよび2バイト文字の「区」を表す上位バイトを
「実行時に」解釈する必要がある
つまりランタイムはASCIIのつもりで文字列を解釈しては駄目で、
Shift JISというものを知っている必要があり、これが
>Shift JIS を使う設定にしてないときに Shift JIS を渡したら駄目かもね。
につながるんだと思う。

863 :デフォルトの名無しさん:2024/06/17(月) 00:57:00.44 ID:pXzMaPAe.net
しかし
>実行環境の都合で各種の変換を入れても良い。
とC++の仕様には書いてあると言っても実際には透過的でない文字コード変換とか有り得ないんでないので?
例えば
ofstream ofs("foo.txt"); ofs << "アイウエオカキクケコ\nさしすせそ" << endl; // (1)
std::string s1, s2;
ifstream ifs("foo.txt"); ifs >> s1 >> s2; // (2)
とやったらs1、s2とも中身は(1)の記述をコンパイル時に解釈した通りになる、
という期待動作しかありえないのでは……
具体的には
s1の中身は SI アイウエオカキクケコ SO の12バイト(末尾NUL除く)になって、
s2の中身は さしすせそ という10バイト(末尾NUL除く)になる、

864 :デフォルトの名無しさん:2024/06/17(月) 01:13:07.47 ID:pXzMaPAe.net
いやトチ狂ったスマンヌ、
Shift JISの2バイト文字は上位下位ともコントロールコード('\r' や '\n' を含む)とはバッティングしないから
>>862 の理解はやや的を外していた……orz
テキストモードにおける '\n' <--> '\r\n' 変換は、ランタイムがShift JIS文字列をASCIIとして解釈してそれを行っても何ら問題を生じない。

しかし、であればやっぱ>>860に戻って、実は実害無いのでは……
Shift JISの2バイト文字は上位下位とも数字とかともバッティングしないようになっているし……
透過的でない文字コード変換(>>863)が無い限り、cout して cin して結果が変になるケースが思いつかなsげ……
(正確には char c; cin >> c; で 2バイト文字 "陰" の2バイト目を "A" として受け取ってしまう、系の避けようが無い事故は除く

865 :デフォルトの名無しさん:2024/06/17(月) 16:31:20.06 ID:prlYSpwu.net
wstringがutf-32だったら良いのに

301 KB
新着レスの表示

掲示板に戻る 全部 前100 次100 最新50
名前: E-mail (省略可) :

read.cgi ver.24052200