C++相談室 part138
■ このスレッドは過去ログ倉庫に格納されています
次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part137
http://mevius.5ch.net/test/read.cgi/tech/1531558382/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.103【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1530384293/
■長いソースを貼るときはここへ。■
http://codepad.org/
https://ideone.com/
[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured devirtualizationはまだclangだけ? Win10で、でかいメモリを使おうとすると0xc0000017で落ちるんだけど
制限を解除する方法あったっけ? 「64bitのコードでコンパイルするよう指定」するやつだっけ?
「デカいメモリ」「エラーコード〜でブルースクリーン」ていう
キーワードで、記憶に引っかかる感じ。 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0551r3.pdf
C++20で、std空間内で宣言されたテンプレートをユーザが特殊化するのを
禁止しようって提案が出てるみたいなんだけど、どうよ?
俺はhashが特殊化できないのは困ると思うんだが ちょっとありえない気がする。大量のコードの互換性が失われるよね。
ostream/wostreamも存在意義を真っ向から否定するような変更では? >>99
pdfは読んでいないが妥当だろう。生産性は上がる。
特殊化したければオレオレ名前空間でstdを継承し、それを使え、でいい。
stdを直接変更している糞コードなんてどこかの時点で切り捨てる必要がある。
それがそろそろだという判断だろうし、実際、妥当だと思う。 >>101
ちなみに、おまえさんは
std::unordered_set<my_class> the_obj; //C2280
こんなのにどう対応しているんだ? しかもstdという空間名だけ、言語が特別扱いとかおかしいだろ エラー出るんだけどさ
mt19937 en;
int ep[en.state_size];
random_device rd;
generate(begin(ep), end(ep), rd); //C2280
このラムダみたいなことをやってくれる標準の何かない?
generate(begin(ep), end(ep), [&rd]{ return rd(); }); generate(begin(ep), end(ep), en)
は? >>109
このあと、en.seek(begin(ep), end(ep)); とやりたいわけで。。。 >>107
generate(begin(ep), end(ep), ref(rd)); >>111
thx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
これを待っていた >>100
亀レスすまそ
なぜostream/wostreamの存在意義を否定することになるんだ? そもそもP0551R3で禁止されるのは関数テンプレートの特殊化についてであって
std::hashなんかのクラステンプレートの特殊化は特に禁止されないのでは?
クラステンプレートの特殊化まで禁止されるとstd::tuple_sizeみたいなユーザによる特殊化ありきの機能が軒並み消滅する事になると思うんだが >>102
>>101じゃない&亀レスですまんけど、
普通にHasher関数オブジェクトを自作して、std::unordered_setのテンプレート第二引数として渡せばいいんじゃないか?
わざわざC2280の解決のためにstd::hashを特殊化するのはナンセンスだと思われる
example:
https://wandbox.org/permlink/mSO96qJDavoK1jqI >>117
テンプレートへの渡し方が微妙だけど可能
autoでラムダ受け取っておいてdecltypeで渡すか、std::functionを受け皿にするかだな
example:
https://wandbox.org/permlink/qDm0vA6MWDrIksih >>116
それやはやだな
せっかく第2引数を省略する方法が提供されているのに
わざわざオレオレファンクタ−作んなきゃいけないのって。。。 ごめ、ありえない変換ミス()しちまった
-それやはやだな
+それはやだな
俺、純血の日本人だよ
信じて 作れるものと作れないものは同じだ
文法的に「すごい」のというと、たとえばラムダ式とか構造化束縛、raw-string-literalあたり
型推定もCで頭固くなっちまった人にはそこそこカルチャーショックだよ >>124
型推論は他の言語でもあるからそんなに驚きはないけどraw string literalはやり過ぎだろ >>123
・例えばAIライブラリは速度面からC++で組まれることが普通。
・言語コンパイラもコンパイル速度を重視すればC++が最適。
・AndroidOSそのものもC/C++で組まれる。
・Java Virtual Machineも、PC EmulatorもC/C++で組まれる。
・同程度の性能のデバイスでAndoidとiOSを比べたとき、前者が遅いといわれるのは
全社はJava(仮想コードにコンパイルされる)、後者はSwing(native binaryにコンパイルされる)
からが大きいと考えられる。 >>130
では Java で記述されたコードをコンパイルした成果物が native binary であればいいのですね、これは商機があるかもしれませんね 甘いな
native binaryでありさえすればいいってもんじゃない
上手いマシン語と下手なマシン語がある >>131
実は、>>133が指摘してる通り JavaやC#は言語仕様そのものが native binary
に直してもC++ほどの速度にはなりにくい。例えば遅くなる理由として
1. GC(Garbage Collection)によって自動的にfreeやdeleteさせようとする仕様。
2. 標準的にはポインタを使わない仕様。
3. オブジェクトが構造体やスタックに埋め込まれずにheapからnewされ易い仕様。
4. 二次元以上の配列がJaggyタイプに成り易い仕様。
5. バッファオーバーランの防止のため、配列の境界チェックが行われやすい仕様。
6. ライブラリが巨大なため起動時に大量のコードがディスクから読み出されるため、
起動が遅く成り易いこと。巨大になる理由の一つはリフレクションや型に
#includeによる静的コンパイルをせずにすますためののクラスの型情報などが
(Javaの場合は*.classや*.jarなどの)ライブラリに入っているためだろうか。
例えば、C#も予めnative binaryに直してしまう方法も有るが、それでも起動速度は
余り早くならないらしい。起動後も1.〜5.の理由のためC++程の速度にはなりにくい。 >>134
7. C#のリンクリストの場合、要素を削除する場合、文字列などの要素の中身か、
要素番号を指定する必要が有る。要素Bを有る要素Aの後ろに追加する場合、
Aの要素番号を指定する必要が有る。これが遅くなる。C/C++本来のリンクリストは
削除や追加の場所の指定をポインタ(アドレス)で指定できることが速度上の大きな
優位性であったのにそれが出来ない。なお、詳しくはないがC++のSTLのstd::listの場合は、
同様の「不具合」があるためリンクリストの本来の性能が出ないかもしれない。
しかし、それはSTLがC/C++の昔から使われていた本来のリンクリストの実装の仕方を
していないからであると思われる。 Javaってランタイムがプリミティブなってるクラスを実行することがあったと思うけど、
ネーティブではそのプリミティブ型のクラスを分解してマシン語にしないといけなかった気がする。 vs2019なんだけどさ
void f(path&& pt)
{
auto date = last_write_time(pt);
auto val = decltype(date)::clock::to_time_t(date); //C2039
}
これどうやってtime_tもらうの? decltype(ftime)::clock::to_time_t()
は、decltype(ftime) が std::filesystem::file_time_type なので、
意味的には長く書けば、
std::filesystem::file_time_type::clock::to_time_t()
となるとは思う。短くすれば、
file_time_type::clock::to_time_t()
となるけど、clock という名前空間は見つからなかったが、
std::chrono::system_clock::to_time_t()
という関数ならば存在しており、
static std::time_t to_time_t( const time_point& t ) noexcept;
という宣言にはなっているところまでは見つけた。
clock というキーワードが何なのかは不明。 last_write_time() の型は:
std::filesystem::file_time_type last_write_time(const std::filesystem::path& p);
file_time_type の型(?)は:
using file_time_type = std::chrono::time_point<>;
なので、
decltype(date)::clock::to_time_t() の部分は、decltype()部分を展開(?)すれば
std::chrono::time_point<>::clock::to_time_t()
と書けることは書ける。この部分は、存在することが分かっている:
std::chrono::system_clock::to_time_t()
ととてもよく似ている。 https://cpprefjp.github.io/reference/chrono/time_point.html
↑によれば、time_pointは
namespace std {
namespace chrono {
template <class Clock, class Duration = typename Clock::duration>
class time_point;
}}
というテンプレート・クラス。
file_time_typeは、C++20では、
using file_time_type = std::chrono::time_point<std::chrono::file_clock>;
と定義されているので、Clock=std::chrono::file_clock とされてテンプレートが具現化される
らしい。time_point<Clock,Duration>クラスには
Clock clock;
というメンバが存在するらしい。ゆえに、
decltype(date)::clock::to_time_t()は、
std::chrono::time_point<std::chrono::file_clock>::clock::to_time_t()
となり、clock=std::chrono::file_clock という意味になり、結局、
std::chrono::file_clock::to_time_t()
ということになるようだ。 >>140
file_clock は、仕様がまだ決まって無いらしい。 うん、俺もそう読んでる
auto sdat = time_point_cast<time_point<system_clock, system_clock::duration>>(date);
・・・これもうまくいかんなあ autoやめるか、autoで得たものをTYPEIDに物故むか。
好きな方をえらぶのじゃ。 >>134-135
動的にコンテナサイズが変わるものは、遅くなる
それと、C++ でも仮想関数を使うと、関数のアドレスが静的に決まらないから、
その都度、計算するから、オーバーヘッドになる void f(path&& pt)
{
auto date = last_write_time(pt);
using dt = typename decltype(date)::clock;
auto val = dt::to_time_t(date); //C2039
}
くっそー、もうAPI呼ぶしかねえのか clock_castが実装されるまで待つしかなかろう >>145
単純に
void f(path&& pt)
{
auto date1 = last_write_time(pt);
time_t val1 = std::chrono::system_clock::to_time_t(date1);
}
とすればいいだけのような気がする。 >>148
https://code.woboq.org/llvm/libcxx/include/chrono.html
↑によれば、以下の様になっており、time_point は、一般的な
template の time_point<・・・>とsystem_clock::time_pointは
厳密には「別」で、後者は前者を特殊化したものを typedef宣言
している。そのため、 std::chrono::system_clock::to_time_t()の
(メンバ)関数宣言の
static time_t to_time_t(const time_point& t) noexcept;
のtime_pointは、chrono::time_point<system_clock>という
system_clock専用になっている。それが原因で>>147は
エラーを出すらしい。
class system_clock {
public:
・・・
typedef chrono::time_point<system_clock> time_point;
・・・
} そう思ってtime_point_castしてみたんだが、それすら通らない。。。 >>150
time_point_cast() は根本的な「Clock」の部分は変換前後で共通の場合のみが
実装されているようです。なのでどこまでの細かい時間を表現できるかの
「時間精度」は変更できても、表現の違いのようなものまでは対応できないのかも
知れません:
namespace std {
namespace chrono {
template <class ToDuration, class Clock, class Duration>
time_point<Clock, ToDuration>
time_point_cast(const time_point<Clock, Duration>& t); // C++11
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
time_point_cast(const time_point<Clock, Duration>& t); // C++14
}} テンプレートとマクロのメリットデメリットって他にありますか?
またテンプレートとマクロの使い分けで悩んでいます
マクロのメリット
・一括置換ができる
・文字列も使用できる
・定数式にも使える(配列の要素数)
マクロのデメリット
・数式が複雑なときにミスをしやすい(++を渡してはいけない、演算優先順位がミスしやすい)
・型の識別ができない
・一行記述なので大規模なのには不向き
テンプレートのメリット
・名前空間を定義できるので影響範囲をとどめやすい
・型の識別ができる
・関数なので大規模なのも書ける
テンプレートのデメリット
・定数式にしようできない
・ユーザー定義と標準定義が混ざったときのエラーを判別しにくい
こんなメリットデメリットだと思っています。
他にありますか??
これを踏まえた上で使い分けとしては、
マクロは文字列などの簡単な定義に向いていて、テンプレートは処理(演算)を含むものと考えているのですが、
他に観点あるでしょうか マクロのデメリット
・スコープに従わない ←致命傷
・デバッガとの相性が極悪 >>152
「他にありますか?」の答えにはならないんだけど・・・
> テンプレートのデメリット
> ・定数式にしようできない
そんなことなくね?
> ・ユーザー定義と標準定義が混ざったときのエラーを判別しにくい
どういう状況のこと言ってるのかよくわからないけど、マクロにすればわかりやすくなる状況なのか
怪しい気がする。
ってことで、使い分けとしてはマクロでしかできないこと(トークン連結・文字列化)以外は
テンプレート使うとしたほうが簡単だと思うし、よく聞く話。 マクロはコンパイラが展開後のコードを見せてくれるけどテンプレートは見せてくれない 展開じゃないからな
typename Tに何が来ているかなんてのはcout << typeid(T).name()で監視できるんで
iocccなみに解読困難なプリプロセッサ出力がないからって困りゃせん その監視というか確認の煩雑さは、マクロの方が面倒だろに。 >>152
マクロは、テンプレートのメタ側に位置する機能なので、テンプレートに出来ない事や、テンプレート自体のコードに変更を入れる場合につかうと良い。
まあ、リテラルレベルの置換と、プリプロセッサの入力に使えるってくらいかな。
よく使うのは、コンパイルスイッチくらいじゃないかな。
極稀にリテラルを文字列化したり、リテラルレベルでトークン連結処理したりするくらいかな。
定数はぶっちゃけどっちでも良いけど、式を含むならconstexpr を使うのが c++11の流儀。 >>159
こんなクソみたいな記述入れて一旦ビルドして確かめるとか正気の沙汰じゃねーわ。
cout << typeid(T).name()
マクロもたいがいダメだろうがこれをやらせるって歪んでるとしか思えん。 一旦ビルドしてって、テンプレートはコンパイルしないと何が来るかなんて分からんだろ
>マクロもたいがいダメだろうが
とか雑な切り捨てしてる辺りからしても、めっちゃ初心者とみた >>161
何がどうクソなんだ?
おまえさんのルールの何条に違反しているんだ? >一旦ビルドしてって、テンプレートはコンパイルしないと何が来るかなんて分からんだろ
だからこれがしょうもないってことを言ってるんだが。
静的にコード見て判断しずらい仕組みをなぜ疑問なく使えるのか、そっちのがよっぽど素人感丸出しだよ。 へー、判断しづらいのかw
おまえさ、C++に向いてないよ
もうやめたら? 横からすまんが
cout << typeid(T).name()
はくそださいと思う 宣言だけのテンプレートを使ってエラー吐かせてクラス名確認するのはわりとやる ダサいと言っているその姿がダサいことにくらい気がつけよ
技術板で客観性を全く欠いた戯れ言ぬかしやがって >>164
>静的にコード見て判断しずらい仕組みをなぜ疑問なく使えるのか
これにはテンプレートも含むってこと?
それならまぁ言いたいことはわかる >>161
言ってることは当たってる。C++は、というか、正確に言うと、C++のスレは歪んでる。
C++ってのは結局のところ、何でも出来るように設計されている。
だから、ユーザーがその機能を使うか使わないか、よくよく考えないと逆に色々面倒なことになる。
マクロもテンプレートも上手く使えば素晴らしいが、濫用すると余計に酷くなる。
○○を使えばいい、とか、逆に、○○は禁止、とか、(本来は)単純に切り分けられるものでもない。
この辺は他LL言語やJava/C#等は最初から使える範囲が決まっており、
C++から見ればかなり制限されているから、濫用は出来ない。
結果、「C++の酷いコード」よりは「C#の酷いコード」の方が数段ましなものにはなる。
逆に言えば、C++はプロ仕様で、
自身でコーディングルールをそれなりに決められる人じゃないと適切には使いこなせない。
実際の職場では大概はがんじがらめのルールが決められているはずで、
C++でコーディングルール無しのところなんてないのではないかと思う。
ところがC++のスレは勘違いした素人が多いのか、
C++の新しい文法や小手先テクニックを使って書くことが目的になっている奴が多い。
そして「長期的な保守」を全く考慮してないレスも散見される。
だからここではそういう雑音もきちんと峻別する能力が求められてしまう。
といってもそれもC++の範疇で、つまり「自分で判断しろ」でしかない。
無理ならC#等そういう「馬鹿が使ったらどうしようもなくなる機能」が最初から用意されてない言語を使え、でしかない。
ここで素人相手にマウント合戦なんて意味無いから止めとけ。
> 静的にコード見て判断しずらい仕組みをなぜ疑問なく使えるのか (>>164)
この基準は正しい。
テンプレートに問題があると認識されているのは昔からだ。
ただ、テンプレート以外に上手く同等のコードを得る方法がないから、それでもテンプレートは使われている。
いずれにしても、その機能をどこまで使うかは君が判定するしかない。
実際に動かさないと何が当たっているか分からないテンプレートなんて事実として糞だが、
それでもその方がましならそういう書き方をするときもあるだろう。
全体を見ず、個々の末端の事例でグダグダ言い争っても意味はない。 上っ面しか見てねえやつだな
長期的な保守性という要求から色んな仕様が発明されているのに
ついていけねえ低脳が被害者面しやがる おまえらもういいから、ずーっとC++98使い続けてろよ
それで食っていける仕事があるなら俺たち別に非難しねえ
非難てのも変だけどな >>172
お前最低限メタプログラミングは出来てて言ってるんだよな?
stlとか新機能使ってるだけとか自分で人様に使われるライブラリ書いたことない、とかじゃないよな? >>175
stlが新機能って・・・・おまえいつから更新停止してんだ? >>171
だいたい納得。
別にstl使うなとかそこまで無茶は言わんよ。
unique_ptr なんかも使っていくのは良いと思うし。
ただおれおれ糞テンプレートライブラリは使いたくねーわという話。 アンチテンプレート厨はenable_ifになぜ_tがあるのかとかわからんだろ そこだけ泥縄で調べて何かぬかすんだろうけど
言ってることの全体的な薄っぺらさはどうにもならねえぜ >>157, >>181は別人だと思ってたんだが違うのか
>enable_ifになぜ_tがあるのか
別にアンチじゃないけどそれはある程度基礎が出来てる人には常識だとおも >>180
まあそうなんだが、unique_ptrとstlで大体いけるならPython/Ruby/Java/C#で全く問題ないし、
それらを使う方が断然生産性が高い。
だから逆に、C++を使うのならそれなりの理由が必要で、
通常それは速度、つまりゴリゴリに手動チューニングしてでも最速を得たい、ということなのだが、
C++のスレは「ナマポは撲滅されるべき、今時スマポ使わないなんて話にならない」だから終わってる。
ナマポを混在させられることがC++のメリットだし、それを使わなければC++使う意味ないと思うが。
あと、C++が導入したのは「オブジェクト指向」と「テンプレート」だが、
オブジェクト指向の方はほぼ全部のメジャー言語に採用されたのに対し、
テンプレートの採用は皆無だろ。出来も推して知るべし。
生産性を追求するC#、安全性を追求するJavaからは要らない子扱いされてるのが現実だ。
個人的に思うのは、超最速を目指さない限りC++で全部組むのはナンセンスで、
GUI部分とかはPython等で楽に組んで、演算部分だけCのDLLを呼ぶのがいいと思う。
Cは大規模コードを組む為の仕組みがないので次第に大きくなってくるとなかなか厳しくなるが、
この方法だと各DLLは1k行程度で済むのでCでも問題になることはない。
なお手動チューニングするならCの方が楽だ。
C++はコンパイラが最適化する前提でテンプレートを重ねがけする事が常態化しており、
ソースコードからどんなオブジェクトコードが生成されるかが読みづらい。
といってもこれはCはあんまり最適化しないからであって、
糞コードであっても速いオブジェクトが出る可能性のあるC++の方が断然いいのも事実だが。
(Cは糞コードなら糞オブジェクトしか出ないが、C++はコンパイラでの最適化がかなり期待できる局面もある)
なお今から学ぶならRustもありだと思うぞ。
unique_ptr基本で組むようにデザインされている。(らしい)
問題はRustは本当に立ち上がるか微妙なことだが。
C++が悪い点は多々あるが、それらって結局、そういう書き方をしなければいいだけでしかなく、
結局のところこれがCもC++も(Rustが立ち上がったとしても)死にきらない理由でもある。 >enable_ifになぜ_tがあるのか
こういうのを知ってウキウキするのはよくわかるよw
https://www.fluentcpp.com/2018/05/18/make-sfinae-pretty-2-hidden-beauty-sfinae/
でもいらん機能を無理やり現場に持ち込んで他人に迷惑かけるのは筋違いだから。 はいはい
テンプレート(もちろん自作の)バリバリのコード書いて
それがどれだけ開発効率に影響与えたか、コスト掛けた価値がどれだけあったか
客観的に言えるようになってからほざいてね 本末転倒もいいとこだな
いいか、最も肝心なことは何を実現したかと成果物の質だ
開発効率だのコストだのはその次に考えることで
そこに振り回されて本分を投げちゃいけねえ 都合のいい抜き出し方をするな
その成果物の質のために、どれだけの時間と労力を掛けて
それが質の向上に見合ったものかを客観的に見れるようになってから言えといってんの 別にテンプレート使うなって言ってんじゃないよ
使ってごちゃごちゃ作るからにはそれが本当に後々まで使える便利なもので、
ゆくゆくは長い開発期間を償却できるレベルなのかどうか、そこまで考えると、普通は判断は難しい
テンプレート使う奴が実力あるやつで、やめとけと言うのは老害とかそんなアホな話は有り得ない 経営者目線ならこっちは自営で
ニートのご高説は無用だ ははは、自らの主張を引っ込めたな
そうなるしかないんだけどな ?俺>>184だよ
テンプレートバリバリ使ってコストのバランスに毎日悩んどるわ
ちな俺も自営、元は会社でチームでやってたが ■ このスレッドは過去ログ倉庫に格納されています