1 名前:デフォルトの名無しさん mailto:sage [2021/11/15(月) 18:49:18.44 ID:I69rZ/Of.net] 前スレ C++相談室 part157 https://mevius.5ch.net/test/read.cgi/tech/1628474251/
741 名前:デフォルトの名無しさん mailto:sage [2022/01/24(月) 20:29:40.39 ID:kghIRcG8.net] https://docs.microsoft.com/ja-jp/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp?view=msvc-170
742 名前:デフォルトの名無しさん mailto:sage [2022/01/25(火) 08:07:34.25 ID:m+e4/QVD.net] めずらしい 変態に興味あるとは VisualJ++とかワケ
743 名前:ワカだったぜw [] [ここ壊れてます]
744 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 05:15:43.56 ID:DGJ/MazB.net] 1秒おきのタイマーでtmDraw()を呼んで右に伸びる四角を描くプログラムです。VSCでMFC未使用。 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: OnPaint(hWnd); break; case WM_CREATE: SetTimer(hWnd,1,1000,(TIMERPROC)NULL); //タイマー定義 break; case WM_TIMER: //タイマー { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); tmDraw(hdc); //これを呼んで描画 EndPaint(hWnd, &ps); } break; return 0; } static VOID tmDraw(HDC hDC) { SetDCPenColor(hDC, RGB(0x99, 0x66, 0x00)); //ここが呼ばれてるのは確認 SetDCBrushColor(hDC, RGB(0xFF, 0xCC, 0x00)); Rectangle(hDC, SIZE16(0, 0, cx++, 6)); //伸びる描画 } 最初の1回の描画はされます。タイマーでtmDraw()が呼ばれてるのは確認しています。 呼ばれて描画されてるはずなのですが、実際の画面は更新されず四角は伸びません。 windowサイズを手動で変えていくと四角は右に伸びていき更新されます。 タイマーでtmDraw()が呼ばれた時に描画だけでなく画面の更新もされるようにするにはどうすればよいですか?
745 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 06:35:00.77 ID:R08bxH5q.net] WM_TIMERでBeginPaintはおかしいぞ WM_PAINT専用なんだから 無効領域ないのにBeginPaintしたらあかん [誘導] 続きはこっちでな Win32API質問箱 Build127 https://mevius.5ch.net/test/read.cgi/tech/1639053176/
746 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 07:17:52.16 ID:T9eKedNN.net] InvalidateRectとかGetDC〜ReleaseDCだっけ?
747 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 07:50:18.18 ID:td9ayUMw.net] アップデートはマイクロソフトがやりたい時にやる という基本理念を理解していないようだね
748 名前:デフォルトの名無しさん [2022/01/26(水) 09:14:18.23 ID:m89Xdimf.net] WM_TIMERでInvalidateRectしておくとWindowsがWM_PAINT呼んでくれるからそこで描画するんだっけ
749 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 09:17:55.57 ID:qvNTvCwo.net] そもそもこれCだろ… WinMainから書く超基礎的コードをここで聞く頭がもうね
750 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 09:26:13.12 ID:WR8doP3S.net] べつにアイドルループで描画してもいいんだよ メッセージの処理さえ忘れずにピークしてこなせば
751 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 09:32:54.79 ID:g/1zEXcm.net] >>738 スレチなのは確かだが、いちいち見下して何がしたいんだお前
752 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 09:36:18.65 ID:dkXO6/An.net] どこにでもいるんだよ 自分より下の者をいたぶることで 安心しようとするチンピラ気質なやつは
753 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 10:21:44.17 ID:qvNTvCwo.net] だってココ定期的に湧くじゃん Windows使っててWin32APIの使い方聞いてくるC++ほとんど知らない自称天才のバカ 同じやつだよきっと 毎回Win32APIに誘導されてるってのにな
754 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 10:46:25.17 ID:g/1zEXcm.net] あー、言われれば確かにそんなの居たっけ・・ でもまぁ同一人物とは限らないんだし誘導して終わりでいんじゃね たまに見当違いの初心者は入ってくるし(DirectXスレにDirectXランタイムのインスコの仕方聞きにきた猛者が居た
755 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 10:59:27.08 ID:vhiSf69I.net] 733 すいません、そっちのスレは知りませんでした そちらで聞き直します
756 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 11:06:01.05 ID:qvNTvCwo.net] DirectXスレにDirectXランタイムのインスコの仕方聞くのはまだ仕方ない話 ドライバ固有の問題に当たっているなら専門家に聞いた方がいいだろう 自称天才のバカである確率の方が高いと思うし、高確率で単発IDで荒らすバカも同じだろうし、わざわざレスしてくるやつも同じだろうから、バカにはバカと言ってあげた方が親切
757 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 12:02:29.99 ID:dkXO6/An.net] 誘導ももう済んでるのに どうしても喧嘩言葉を使いたくて沸いてくる 三下のそのまた下の家畜はいいのか
758 名前:デフォルトの名無しさん [2022/01/26(水) 13:23:53.73 ID:m89Xdimf.net] DirectXランタイムが許されるならWin32 APIだって許してあげなよ 製品名はVisual C++だし、既定の拡張子 .cpp なんだから Win32はC++ではなくCだって言ってもしょうがない
759 名前:デフォルトの名無しさん mailto:sage [2022/01/26(水) 23:06:08.50 ID:UuxYD5f6.net] いかにも漏れは天才だが さすがにWinMain()から書くようなバリバリWindowsアプリの質問はしないかなあ、、、 漏れの言ってることがまるで理解できない低レヴェル凡人の反発を招くことはあってもな
760 名前:デフォルトの名無しさん mailto:sage [2022/01/27(木) 10:59:27.25 ID:Z+Vqme3O.net] 天才でも質問することあるんですね 回答者は超天才?
761 名前:デフォルトの名無しさん mailto:sage [2022/01/27(木) 11:49:44.22 ID:avZQ9Wm7.net] いかにも 私が超天才だが ってどっかのハンコ貰いにいく人事のCMみたい
762 名前:デフォルトの名無しさん mailto:sage [2022/01/29(土) 15:04:46.13 ID:mo0R2qbj.net] 大学の課題でコンパイルエラーになるので教えてもらいないでしょうか main.cppで、B<A> b; b.display(); のようにAを使っています。 g++ -Wall -std=c++17 -g -o test a.cpp main.cpp undefined reference to `operator<<(ostream&, A const&)' ※コンストラクタなどの関数定義は省略してます。 ■ a.h class A { public: string m_str; friend ostream & operator << (ostream &os, const A &a); }; ■ a.cpp ostream & operator << (ostream &os, const A &a) { os << a.m_str << endl; return os; } ■ b.h template <typename T> class B { public: void display(ostream &os = cout) const; T m_dummy; }; template <typename T> void B<T>::display(ostream &os) const { os << m_dummy << endl; // ここが undefined referenceエラー }
763 名前:751 mailto:sage [2022/01/29(土) 15:50:41.96 ID:mo0R2qbj.net] 失礼、自己解決しました。 namespaceをa.hだけ括って、a.cppに入れ忘れましたw
764 名前:デフォルトの名無しさん mailto:sage [2022/01/31(月) 02:23:38.98 ID:iz74n4+D.net] 下の★1を★2のように書きたいんだけど、どうやって書けばいいのか 教えてぇ #include <iostream> template <typename T> auto Sum(T h) { return h; } template <typename Head,typename... Rests> auto Sum(Head head,Rests... rests) { return head + Sum(rests...); } template<class F,class... Args> auto foo(F&& f,Args... args) { return f(args...); } int main( int argc, char *argv[] ) { std::cout << foo(Sum<int,int,int>,1,2,3) << "\n";//★1 //std::cout << foo(Sum,1,2,3) << "\n"; //★2 }
765 名前:はちみつ餃子 mailto:sage [2022/01/31(月) 04:05:32.34 ID:y6tOo2ii.net] >>753 そのようには書けない。 C++ では高階多相を許していない。
766 名前:デフォルトの名無しさん mailto:sage [2022/01/31(月) 04:18:19.49 ID:o5RGUewZ.net] なんでも適当に済ますクセ 高級言語に慣れすぎの弊害
767 名前:デフォルトの名無しさん mailto:sage [2022/01/31(月) 14:49:02.61 ID:y2HjUy1l.net] >>753 ・まず、Sumを多重定義にする必要性は特にないはず ・次に、fooが関数でSumが関数テンプレートの場合、 関数の実引数として具現しないテンプレートは渡せない だからfooの代わりにstd::bindを使っても解決しない ・テンプレートテンプレート仮引数を使っても クラステンプレートしか渡せず関数テンプレートは不可 こうなるとマクロくらいしか手がない #define foo(func, ...) func(__VA_ARGS__)
768 名前:デフォルトの名無しさん mailto:sage [2022/01/31(月) 16:24:09.60 ID:4mzN2AL1.net] 戻り値のautoが決まらないってことでしょ?autoをdouble固定にしてReturnをなくせば通る #include <iostream> auto sum() {return 0;} template<typename Head> auto sum(Head head) {return head;} template<typename Head, typename... Tails> auto sum(Head head, Tails ...tails) {return head + sum(tails...);} template<typename Return, typename... Args> Return wrap(Return (*f)(Args...), Args ...args) {return f(args...);} int main( int argc, char *argv[] ) { std::cout << sum(1,2.1) << std::endl; std::cout << wrap(static_cast<double(*)(int,double)>(sum), 1,2.1) << std::endl; std::cout << wrap(sum<int,double>, 1,2.1) << std::endl; std::cout << wrap(sum, 1,2.1) << std::endl; return 0; } // /usr/bin/g++ -fdiagnostics-color=always -g /home/user/cpp/autoreturn/sample.cpp -o /home/user/cpp/autoreturn/sample // /home/user/cpp/autoreturn/sample.cpp: In function ‘int main(int, char**)’: // /home/user/cpp/autoreturn/sample.cpp:10:29: error: no matching function for call to ‘wrap(<unresolved overloaded function type>, int, double)’ // 10 | std::cout << wrap(sum, 1,2.1) << std::endl; // | ^ // /home/user/cpp/autoreturn/sample.cpp:5:52: note: candidate: ‘template<class Return, class ... Args> Return wrap(Return (*)(Args ...), Args ...)’ // 5 | template<typename Return, typename... Args> Return wrap(Return (*f)(Args...), Args ...args) {return f(args...);} // | ^~~~ // /home/user/cpp/autoreturn/sample.cpp:5:52: note: template argument deduction/substitution failed: // /home/user/cpp/autoreturn/sample.cpp:10:29: note: couldn’t deduce template parameter ‘Return’ // 10 | std::cout << wrap(sum, 1,2.1) << std::endl; // | ^
769 名前:デフォルトの名無しさん mailto:sage [2022/01/31(月) 20:55:29.83 ID:ExACmeMg.net] >>753 auto Sum = [](auto head, auto... rests) { return (head + ... + rests); };
770 名前:デフォルトの名無しさん mailto:sage [2022/01/31(月) 22:50:37.06 ID:67CF9RIT.net] ラッパークラスを通せば似たようなことはできそう。 struct Wrapper_ { constexpr static auto doit = [](auto... args) { return Sum(args...); }; } wrapper; int main( int, char ** ) { std::cout << foo(wrapper.doit,1,2,3) << "\n"; }
771 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 04:38:50.89 ID:X9o0BiPI.net] クラスは不要だった。 ラムダなら通るみたいだから、 >>758 みたいに元の関数をラムダで書くか、 auto wrapper = [](auto... args) { return Sum(args...); }; みたいなラッパー関数オブジェクト通すかってあたりで足りそう。 // 最初実験してたとき、ラムダ式にしただけだとエラー出てた気がしたんだけど、今やると問題なく通る…
772 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 05:38:09.33 ID:wGiSz27Y.net] おお、auto... なんてできたのか
773 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 07:53:40.48 ID:vPA4cgbg.net] >>757 にラムダ入れた。 ラムダはオーバーロードできずC++17の畳み込み式が必須で引数なしが表現できないが、選択の手間がない。 #include <iostream> auto sum() {return 0;} template<typename Head> auto sum(Head head) {return head;} template<typename Head, typename... Tails> auto sum(Head head, Tails ...tails) {return head + sum(tails...);} template<typename Return, typename... Args> Return wrap(Return (*f)(Args...), Args ...args) {return f(args...);} auto lambda_sum = [](auto head, auto ...tails) {return (head + ... + tails);}; // 追加 auto lambda_wrap = [](auto f, auto ...args) {return f(args...);}; // 追加 int main( int argc, char *argv[] ) { std::cout << sum() << std::endl; // 追加 std::cout << sum(1) << std::endl; // 追加 std::cout << sum(1,2.1) << std::endl; std::cout << wrap(static_cast<double(*)(int,double)>(sum), 1,2.1) << std::endl; std::cout << wrap(sum<int,double>, 1,2.1) << std::endl; // std::cout << wrap(sum, 1,2.1) << std::endl; // エラー // lambda版追加 // std::cout << lambda_sum() << std::endl; // エラー std::cout << lambda_sum(1) << std::endl; // 追加 std::cout << lambda_sum(1,2.1) << std::endl; std::cout << lambda_wrap(static_cast<double(*)(int,double)>(sum), 1,2.1) << std::endl; std::cout << lambda_wrap(static_cast<double(*)(int,double)>(lambda_sum), 1,2.1) << std::endl; std::cout << lambda_wrap(sum<int,double>, 1,2.1) << std::endl; // std::cout << lambda_wrap(lambda_sum<int,double>, 1,2.1) << std::endl; // not template // std::cout << lambda_wrap(sum, 1,2.1) << std::endl; // エラー std::cout << lambda_wrap(lambda_sum, 1,2.1) << std::endl; return 0; }
774 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 22:23:26.64 ID:rdLB3H0G.net] c++では sz=120; char dt[sz]; このように配列のサイズを変数の可変サイズで指定することはできないんですか? これを実現する方法は何かありませんか?
775 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 22:43:02.67 ID:rdLB3H0G.net] 自己解決しました しかし dt[10][d] のように2次元以上はjavaのような動的変動はできないんですね
776 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 23:27:31.22 ID:fhOfpvRh.net] vector使わんの?
777 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 23:28:28.99 ID:hJiWfYJV.net] 配列使わんし
778 名前:デフォルトの名無しさん mailto:sage [2022/02/01(火) 23:30:45.06 ID:Sh1zYLGa.net] >>763 arrayという似たようなやつはあるが 基本的に作法が違う
779 名前:デフォルトの名無しさん mailto:sage [2022/02/02(水) 10:03:42.12 ID:pPu7Tazo.net] コンストラクタ・テンプレートでテンプレート実引数を推定させず明示的に与えるのはどう書く? struct some_class { template <class A> some_class(int) {} }; int main() { some_class obj<void>(1); //error }
780 名前:デフォルトの名無しさん mailto:sage [2022/02/02(水) 12:11:02.47 ID:ryNE78sg.net] >>768 コンストラクタには明示的に型引数を渡せない
781 名前:デフォルトの名無しさん mailto:sage [2022/02/02(水) 12:36:54.65 ID:pPu7Tazo.net] そっか。。。残念 thx >>769
782 名前:デフォルトの名無しさん mailto:sage [2022/02/02(水) 12:56:51.10 ID:X/91R13x.net] ファイルサイズを取得しようとしていろいろサイトを参考にして次のようにしたのですが std::filesystem::file_size(path) filesystemのところに赤線が出て使用できません これらは記述しています #include <iostream> #include <fstream> #include <filesystem> 使っているのはCommunity 2019です filesystemが使えないのはなぜでしょう?
783 名前:デフォルトの名無しさん mailto:sage [2022/02/02(水) 13:02:34.63 ID:ryNE78sg.net] >>771 filesystemが使えるのはC++17以降 プロジェクトの設定から言語バージョンをC++14(既定)->C++17に
784 名前:デフォルトの名無しさん mailto:sage [2022/02/02(水) 13:34:32.24 ID:pPu7Tazo.net] >>771 /std:c++17は指定してる?
785 名前:デフォルトの名無しさん mailto:sage [2022/02/02(水) 13:43:30.57 ID:X/91R13x.net] ありがとうございます C++17指定できました
786 名前:デフォルトの名無しさん mailto:sage [2022/02/03(木) 12:49:10.84 ID:d1XPVqCl.net] filesystemは、できればC++20モードで使いたい file_clockまわりがC++17ではgdgdだから
787 名前:デフォルトの名無しさん mailto:sage [2022/02/04(金) 13:06:35.94 ID:ovGR74Kw.net] 小文字に変換するプログラムです string toLowerCase(const string& str) { string lower = str; std::transform(lower.begin(), lower.end(), lower.begin(), std::tolower); return lower; } 実行するとstd::transform 一致するオーバーロードする関数が見つかりません、とか 6引数が必要です 4が設定されてます、とか出て 実行できません これは何が問題なのでしょうか?
788 名前:デフォルトの名無しさん mailto:sage [2022/02/04(金) 13:07:58.25 ID:N/NFryku.net] tolowerが多重定義関数だからじゃね?
789 名前:デフォルトの名無しさん mailto:sage [2022/02/04(金) 13:22:13.60 ID:ovGR74Kw.net] 自分では他に定義してないんですがどこで定義されてるんでしょう
790 名前:はちみつ餃子 mailto:sage [2022/02/04(金) 13:28:07.50 ID:RpLWwySn.net] >>776 ちょうど >>658 で同じような事例が出ている。 std::tolower は cctype ヘッダと locale ヘッダにそれぞれあって locale ヘッダのほうが関数テンプレートだし二引数なのでこの場の都合に合わない。 なんらかの方法でどれを使うのか選択する必要があり、 たとえば static_cast などが使える。 ただ、 >>661 が提示しているようにデフォルト引数が追加される可能性があったりもするので static_cast よりはラムダ式を経由するほうが安心できるスタイルかもね。 #include <iostream> #include <string> #include <algorithm> #include <cctype> std::string toLowerCase(const std::string& str) { std::string lower; std::transform(std::begin(str), std::end(str), std::back_inserter(lower), static_cast<int(*)(int)>(std::tolower)); return lower; } int main(void) { std::cout << toLowerCase("abcDEfgHi") << std::endl; }
791 名前:デフォルトの名無しさん mailto:sage [2022/02/04(金) 13:35:40.02 ID:ovGR74Kw.net] ありがとうございます ビルド通ったみたいです
792 名前:デフォルトの名無しさん mailto:sage [2022/02/04(金) 13:55:24.36 ID:3M0ClPfa.net] 最近のはptr_funやんなくても通んだな
793 名前:デフォルトの名無しさん mailto:sage [2022/02/05(土) 11:50:25.88 ID:DOE5sh/+.net] template<yyy T>//yyyはコンセプト requires !xxx<T>//xxxはコンセプト void test(const T& a);//yyyのコンセプトを満たしxxxのコンセプトを満たさないものについて処理したい C++20のコンセプトのrequires節って!使うと警告出るのでわざわざ否定用のコンセプト作成して対応してるんだけど、もっと簡単な仕組みない?
794 名前:デフォルトの名無しさん mailto:sage [2022/02/05(土) 11:52:48.48 ID:vpksE3yJ.net] requires (!xxx<T>)
795 名前:デフォルトの名無しさん mailto:sage [2022/02/05(土) 12:04:00.17 ID:DOE5sh/+.net] 解決した!ありがとう!
796 名前:デフォルトの名無しさん mailto:sage [2022/02/05(土) 20:23:31.04 ID:Irrrknzv.net] #define FOO() 1 #if FOO ... #endif と書いた場合FOOの後ろに()付けるの忘れてるのでコンパイルエラーになって欲しいんですが 実際はFOOは偽に評価されてるみたいです 何が起きてるんでしょうか?
797 名前:はちみつ餃子 mailto:sage [2022/02/05(土) 20:31:08.99 ID:NEwj3nV7.net] >>785 #if の条件の部分ではマクロ展開できるものを全部展開したあとに知らない識別子が残ったら 0 と解釈する。
798 名前:デフォルトの名無しさん mailto:sage [2022/02/05(土) 20:32:57.42 ID:BHACckaU.net] >>785 FOO に () が無いことで展開されず、マクロ展開後に残った識別子として 0 に置き換わってる。 https://timsong-cpp.github.io/cppwp/n4868/cpp.cond#11.sentence-1 > After all replacements ..., all remaining identifiers and keywords, > except for true and false, are replaced with the pp-number 0, ...
799 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 01:29:50.60 ID:Yc7Iwiyd.net] >>785 バカですか?
800 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 01:32:54.82 ID:3BxbnhGH.net] #if defined(FOO) ... #endif
801 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 01:34:05.59 ID:Yc7Iwiyd.net] Cの基本が出来てないくせにC++を使いこなせると思うなよ
802 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 01:35:00.88 ID:H2F64OwB.net] 横からだけど知らなかった
803 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 03:28:00.08 ID:XnD7OQcd.net] >>786 >>787 ありがとうございます このルールは知りませんでした
804 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 06:46:34.29 ID:qvD4QsX7.net] こういう馬鹿のためにコンパイラに無駄なルールが必要になるんだなと実感
805 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 06:55:06.64 ID:usxBX4wT.net] エラーにならないのは理不尽だな
806 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 08:23:12.41 ID:qvD4QsX7.net] 馬鹿のためにわざわざプリプロセスで構文解析エラーを要求するとか馬鹿の極み
807 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 08:30:29.95 ID:usxBX4wT.net] FOOが0になる根拠を与えていないだろ 関連付けられていないものが出てくるのがおかしいと思わないとしたらPG適性低いぞ
808 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 08:53:46.75 ID:2YxKeDPZ.net] 唐突に0がどうとか言い出すのはセンス無いわ
809 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 09:07:44.45 ID:HE5J2RYG.net] 初めて知った
810 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 09:24:54.74 ID:usxBX4wT.net] >>797 >>786
811 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 09:35:58.81 ID:qvD4QsX7.net] 馬鹿は当たり前のように英語も読めない
812 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 09:36:22.76 ID:vWDceL4H.net] なんじゃそりゃ>>799 はC++規格委員会が死ね言うたら死ぬんか、
813 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 09:57:50.12 ID:vWDceL4H.net] 規格書にはなんでそうなっているのか(置換されずに残ったFOOをエラーではなく0にするのか)の理由が書かれていないが #ifdef defined(FOO) && FOO として現れる論理式「defined(FOO) && FOO」の解釈を簡単にやりたい(FOOが未定義の場合でも通常の式の解釈ルーチンで処理したい 的なしょーもない理由だったりして……
814 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 09:59:13.49 ID:vWDceL4H.net] まつがえたorz ×: #ifdef defined(FOO) && FOO ○: #if defined(FOO) && FOO
815 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 10:11:26.46 ID:usxBX4wT.net] >>801 唐突じゃないことを示したまで 事実関係をよく確認してからセンス無いとかドヤれってこと
816 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 10:16:43.48 ID:a0g451d/.net] 理由はたぶん、規格化以前に存在した実装の動作を規格違反とするのはマズいとか、 その動作に依存して #if FOO としてる既存ソースをエラーとするわけにはいかなかったとか、 そんなところだろうと思う。 マズい動作として検出したければ警告は出せるんだし。
817 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 11:57:03.48 ID:qvD4QsX7.net] 馬鹿がまだ騒いでるのかw こういう変なコードとの対比w $ g++ -x c++ - <<EOF auto f = [](){return 2;}; #define f() 1 int main() { auto i = f(); auto j = f; return i + j(); } EOF $ ./a.out $ echo $? 3 $
818 名前:はちみつ餃子 mailto:sage [2022/02/06(日) 12:12:45.00 ID:u7K67HUJ.net] 残った識別子を 0 に解釈する挙動は C89 からの仕様だから C89 の Rationale (根拠) を見たんだけど直接的な言及は見つからない。 https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BxVCLS4f8Sg5NWZmM2NjZWEtYmExMS00Y2EzLWE3ZTMtNzFmYjYwYzBiOTIw&hl=en_US ただ、既存のコードに差し障りがないようにということは明記してある (3.8.3) ので、 その時点でそういう挙動が支配的 (かつそれに依存するコードが多かった) のだろうとは察せられる。 規格ってのは統一を図るってのが第一の目的だけど無理な仕様でまとめちゃうと誰もその規格に従わないだけなんで、 現実にそれでやっているってのも (たとえ不格好でも) 十分な理由になるんだよ。
819 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 12:26:28.98 ID:qvD4QsX7.net] そう書かれるとC89っぽく書かないといかんのか?w 変更部分のみw $ gcc -x c -std=c89 - <<EOF int f(void){return 2;} #define f() 1 int main(void) { int i; int (*j)(); i = f(); j = &f; return i + (*j)(); } EOF
820 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 12:53:10.29 ID:FF40fIFl.net] CとC++の規格は既存コードへの忖度の塊で出来てるからな 万人の敵だったgets()を削除するのにどんだけ苦労してるのやら
821 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 13:16:26.39 ID:vWDceL4H.net] >>806 >>808 スレに乗っかったつもりにしては #if f 〜 #endif というのが含まれて無いようだが?
822 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 13:22:45.35 ID:vWDceL4H.net] >>807 C++規格委員会は無罪なのかもしれんがじゃあなんでC89以前からそうで そういう挙動が支配的になってしまう事態になってしまったのか、と考えると やっぱプリプロセッサの最初の設計者がサボって プリプロセッサ式の途中でのFOOの定義/未定義判定を define(FOO)を導入する代わりに仕様の方を弄って簡単ハックしてしまったから のでは……
823 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 13:33:49.71 ID:qvD4QsX7.net] コードを示しても馬鹿には伝わらない悲しみw
824 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 13:37:12.22 ID:vWDceL4H.net] >>812 天才にもわかるようにkwsk
825 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 13:39:17.55 ID:qvD4QsX7.net] 天才は自力でなんとか出来るし、他人を信用しないことも多いから、基本的に質問とかする機会がない アイデアレベルの話のみ
826 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 14:11:31.07 ID:Yc7Iwiyd.net] (σ゚ω゚)σゲッツ stdioのバッファ使うヤツ殆ど失敗作
827 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 14:22:31.03 ID:yFNvdNoT.net] #define マクロは単純置換のやつと関数形式のやつがある #define A(a,b) A();A(1);A(1,2,3);A(1,);A(,2);A; 結構めちゃくちゃなことやってもプリプロセスはエラー吐かない 引数足りないとか関数形式マクロの括弧がないのは意図しない使い方だろうからエラーにしてもらいたい気持ちはわかるが というか<<802で言及されてるけど#if UNDEFINEDも非推奨にしてほしいわ #define DEBUG #define DEBUG 1 #define DEBUG 0 //#define DEBUG (undefined) これらの全部のケースに対応できてねーし #if DEBUG+0 とか書けとでも?
828 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 15:06:24.27 ID:qvD4QsX7.net] 俺のコードのg++やgccをcppに変えればプリプロセスの結果が出るよw オプション引数に-Eを付けても可w 別に不思議でも何でもない結果が表示されるw $ cpp -x c++ - <<EOF #define A(a,b) expanded A(); A(1); A(1,2,3); A(1,); A(,2); A; EOF # 1 "<stdin>" # 1 "<built-in>" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "<stdin>" <stdin>:2:3: error: macro "A" requires 2 arguments, but only 1 given <stdin>:1: note: macro "A" defined here A; <stdin>:3:4: error: macro "A" requires 2 arguments, but only 1 given <stdin>:1: note: macro "A" defined here A; <stdin>:4:8: error: macro "A" passed 3 arguments, but takes just 2 <stdin>:1: note: macro "A" defined here A; expanded; expanded; A; $
829 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 16:46:37.28 ID:XnD7OQcd.net] インクルードガード書くときも単に #define FOO_HPP とするのと #define FOO_HPP 1 と1にするのがあるがどちらが良いとかあるんだろうか 後者の方がconstexpr if文などのC++の言語機能と組み合わせて使えるというメリットがありそうだが
830 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 16:54:43.06 ID:W01LuusE.net] 今から新規に書くなら #pragma once 一択
831 名前:はちみつ餃子 mailto:sage [2022/02/06(日) 17:09:14.27 ID:u7K67HUJ.net] >>818 私自身は前者にしてる。 インクルードしたことを示すためのフラグとしてのマクロが必要なら (そういう事例に遭遇したことはないが) ガード用とは別にマクロ定義すると思う。 ガードのために定義したものをガード以外の目的で使うというのがちょっと汚く感じるから。 だけど分けちゃうと管理が二重になるのが嫌だと思う人もいるだろうし、 思想によるんじゃないの。 私は規格厨なので #pragma once は使わない。 まあ gcc と clang と msvc で使えるから事実上は問題にならないけど。
832 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 17:25:15.43 ID:XnD7OQcd.net] >>820 ありがとう 納得できる理由です インクルードガード以外のフラグも同様にしてますか? 標準のNDEBUGのように
833 名前:はちみつ餃子 mailto:sage [2022/02/06(日) 17:46:04.51 ID:u7K67HUJ.net] >>821 NDEBUG は「デバッグモードとそうでないモードを切り替える」というのがその用途なので それに沿うと思ったら分けずに NDEBUG を使うことはあるよ。 でも「NDEBUG の用途は assert の有効・無効の切り替えなので他に使うべきでない」と認識している人がいてもおかしくない。 規格に書いてあるのはこの場合はこうだという規則だけなので 抽象的な部分での意味の捉え方は人によってかなり幅がある。 そのあたりは文脈を察して常識的判断でやっていくしかないし、 チームでやってるなら話し合うしかしょうがない。 このへんはそんなにスッパリと判断基準を設けられるようなもんではないと思う。
834 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 19:09:51.99 ID:qvD4QsX7.net] MS発祥のモノが嫌われてるだけとも思うw
835 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 19:46:48.16 ID:XnD7OQcd.net] >>822 質問の意図がわかりにくくてすみません 自前でフラグ書くなら >>818 の前者と後者どちらを使うのかが知りたかった
836 名前:はちみつ餃子 mailto:sage [2022/02/06(日) 20:08:36.06 ID:u7K67HUJ.net] >>824 基本的には前者。 フラグとしてのマクロで分岐するときは #if よりも #ifdef (または defined) を使うようにしてる。 マクロは型を付けられないからそうすることで ON/OFF のどちらかであって内容に意味はない ことを明示してる感じを出したいと思ってる。
837 名前:デフォルトの名無しさん mailto:sage [2022/02/06(日) 20:55:43.12 ID:XnD7OQcd.net] >>825 改めての回答ありがとうございます こういう一見どちらでも良いものであっても裏の考えや意図が聞けて面白かったです
838 名前:デフォルトの名無しさん mailto:sage [2022/02/07(月) 06:01:51.26 ID:a2THiWt1.net] #pragma onceを標準に採用すればええのに これだけ需要あるのに長年ずっと放置状態 何がそん
839 名前:なに問題なんだろう [] [ここ壊れてます]
840 名前:はちみつ餃子 mailto:sage [2022/02/07(月) 09:54:39.71 ID:T4nofIq4.net] 現行仕様での理屈の立て方としては #include の効果でコードに一体化してから内容の解釈が始まるので インクルードに干渉する余地がない。 現実にやってるんだから出来るのは間違いないんだけど理屈を根本から変えることになるし、 モジュールが上手くいけばどうでもよくなることに手間をかけたくないんじゃないかな。
841 名前:デフォルトの名無しさん mailto:sage [2022/02/07(月) 11:19:39.20 ID:3u4X3WRg.net] シンボリックリンクで別のパスになってたりとか、同じ内容の別ファイルとか、ファイル名違う中身同じファイルとか、日付だけ違う別ディレクトリの同じ内容のファイルとか そんなの考えたくないよなーw