前スレ
C++相談室 part156
https://mevius.5ch.net/test/read.cgi/tech/1621389313/
探検
C++相談室 part157
レス数が900を超えています。1000を超えると表示できなくなるよ。
2021/08/09(月) 10:57:31.60ID:JaaB5Egp
836デフォルトの名無しさん
2021/10/23(土) 08:10:22.62ID:LycCK1PV void*よりはちょっとマシって程度の感覚だな
837デフォルトの名無しさん
2021/10/23(土) 10:04:52.59ID:rMqegMI3838デフォルトの名無しさん
2021/10/23(土) 10:05:50.17ID:bwy1yWHL void*「むかしはあんなに愛してくれたのに…」
839デフォルトの名無しさん
2021/10/23(土) 11:08:12.01ID:FGy8rv7m840デフォルトの名無しさん
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が継承(実装)した方がいいと思うってこと?
>>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が継承(実装)した方がいいと思うってこと?
841はちみつ餃子 ◆8X2XSCHEME
2021/10/23(土) 13:07:50.50ID:UQ/XjfNb >>840
そう。 クラスごとに違う挙動が必要ならその違いはクラスの中に隠蔽されているべきで、
クラスを使う側で分岐するのはなんかちょっとあれだなという感じ。
型を調べて分岐するようなコードが嫌だから動的な型を調べる機能を意図的に入れなかった話は D&E にも書かれてる。
(最終的には typeid が導入されてしまったけど……)
ただそれは「型を追加したくなったら分岐も増やすのはめんどいしミスしそう」みたいな話なので、
十分に賢いユーティリティが標準で用意されている今ならそれほど強い動機でもないんだけどね。
そう。 クラスごとに違う挙動が必要ならその違いはクラスの中に隠蔽されているべきで、
クラスを使う側で分岐するのはなんかちょっとあれだなという感じ。
型を調べて分岐するようなコードが嫌だから動的な型を調べる機能を意図的に入れなかった話は 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とか用意してくれんかね。
とりあえずはstd::vector<std::function<std::string()>>に[v](){ return std::to_string(v); };
あたりを入れとくのが簡単かね。
conceptを「その制約を持つクラスの総称クラス」としてshared_ptrあたりで指定できるようになると便利なんだけどなぁ。
concept_shared_ptrとか用意してくれんかね。
843はちみつ餃子 ◆8X2XSCHEME
2021/10/23(土) 13:16:46.64ID:UQ/XjfNb >>837
any_cast での取り出しは「元の型」でなければならず、
string に変換可能な型であっても any_cast<string> は出来ない。
(やったら例外が飛ぶ)
最終的に文字列になると決めているなら文字列にしてから格納したほうがすっきりするんじゃないの。
any_cast での取り出しは「元の型」でなければならず、
string に変換可能な型であっても any_cast<string> は出来ない。
(やったら例外が飛ぶ)
最終的に文字列になると決めているなら文字列にしてから格納したほうがすっきりするんじゃないの。
844デフォルトの名無しさん
2021/10/23(土) 14:23:02.68ID:KcnUiVki >>841
まあそうだよね。ありがとう。
まあそうだよね。ありがとう。
845デフォルトの名無しさん
2021/10/24(日) 08:17:03.78ID:mo2+vXTQ846デフォルトの名無しさん
2021/10/24(日) 08:20:03.55ID:mo2+vXTQ847デフォルトの名無しさん
2021/10/24(日) 08:40:20.31ID:i4dOTOfz 上では例外安全にするとかしないとか言っていたような気がしたが少し主張が変わったのかな。
- 例外安全を求めるのは当然
- RAIIを使えば比較的例外安全を保証しやすい
- だからといってRAIIを使えば自動的に例外安全になるわけではない
結論としてはこんな感じだと思うが。
- 例外安全を求めるのは当然
- RAIIを使えば比較的例外安全を保証しやすい
- だからといってRAIIを使えば自動的に例外安全になるわけではない
結論としてはこんな感じだと思うが。
848デフォルトの名無しさん
2021/10/24(日) 08:41:27.07ID:7jz7Y9vl チェックして例外出さないと解放されないコード書いたのか…
849デフォルトの名無しさん
2021/10/24(日) 09:13:23.68ID:1SVJ9Wvp そりゃ例外安全もRAIIも魔法じゃないんだから使えば即安全になるというわけじゃないわな
「ちゃんと使えば」をすっ飛ばして>>845みたいなことを言い出すのも一種の思考停止だろうと思うわ
「ちゃんと使えば」をすっ飛ばして>>845みたいなことを言い出すのも一種の思考停止だろうと思うわ
850デフォルトの名無しさん
2021/10/24(日) 09:51:02.52ID:v4numFpL >>845
Barのデストラクタの責務は自分が確保したリソースをリークしないことだけだ
オブジェクトの外側でやってるスレッド間通信のことなんかBarは知らんし別に手当するだけの話
逆に聞くがRAIIを嫌がってBar* x = new Bar;とかにしたらなんか事態改善すんの?スレッド間通信を簡潔に書くための役に立つの?
Barのデストラクタの責務は自分が確保したリソースをリークしないことだけだ
オブジェクトの外側でやってるスレッド間通信のことなんかBarは知らんし別に手当するだけの話
逆に聞くがRAIIを嫌がってBar* x = new Bar;とかにしたらなんか事態改善すんの?スレッド間通信を簡潔に書くための役に立つの?
851デフォルトの名無しさん
2021/10/24(日) 10:24:44.80ID:P2kmr3bK そもそもRAIIが例外安全のためっていうイメージ全くないんだけど
リソースのお片付け(≒メモリリーク防止)が主目的ちゃうん?
リソースのお片付け(≒メモリリーク防止)が主目的ちゃうん?
852デフォルトの名無しさん
2021/10/24(日) 10:36:38.75ID:i4dOTOfz 例外が発生するとリソースを片付け損ねる場合があるってのが例外安全を欠く一番よくあるケースだと思うけど。
主目的がどうとかは別として。
主目的がどうとかは別として。
853デフォルトの名無しさん
2021/10/24(日) 10:45:51.44ID:NLtlOSxj >>845
例外を生じた場合でもXとなんらかの通信を行うべきなら
thread_connectionみたいなクラスを作ってデストラクタに整合性を保つためコードを書くのがいいかな
「アプリケーション固有の〜を送る」の部分にはそのオブジェクトのメソッド呼び出しにしておく
例外発生時にはデストラクタによってXスレッドに異常を通知してXスレッドが持つ状態の整合性を確保してもらう
Xに通知するのが単なる終了通知なら(成否を区別して処理しなくていいなら)全部デストラクタでいいかもね
例外を生じた場合でもXとなんらかの通信を行うべきなら
thread_connectionみたいなクラスを作ってデストラクタに整合性を保つためコードを書くのがいいかな
「アプリケーション固有の〜を送る」の部分にはそのオブジェクトのメソッド呼び出しにしておく
例外発生時にはデストラクタによってXスレッドに異常を通知してXスレッドが持つ状態の整合性を確保してもらう
Xに通知するのが単なる終了通知なら(成否を区別して処理しなくていいなら)全部デストラクタでいいかもね
854デフォルトの名無しさん
2021/10/24(日) 10:47:45.55ID:KyFc3YJo 結局コードがないのでまた空中戦になってますね
855デフォルトの名無しさん
2021/10/24(日) 11:38:44.49ID:IQSwOnqn 例外でデストラクタ呼ばないケースなんてあるんですか?
プログラム自体が止まるのは別として
プログラム自体が止まるのは別として
856デフォルトの名無しさん
2021/10/24(日) 12:07:45.68ID:KyFc3YJo リマインダー>>731
857デフォルトの名無しさん
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
#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
858ハノン ◆QZaw55cn4c
2021/10/24(日) 15:13:35.43ID:rOnHPdOM >>838
「「最初から void * な実体」は作らない」「void (*)(void *, ...) くらいまでがせいぜいだ」というように努めていた私は愛し方が足りなかったのでしょうか?
最近の愛し方:https://mevius.5ch.net/test/read.cgi/tech/1624028577/305
「「最初から void * な実体」は作らない」「void (*)(void *, ...) くらいまでがせいぜいだ」というように努めていた私は愛し方が足りなかったのでしょうか?
最近の愛し方:https://mevius.5ch.net/test/read.cgi/tech/1624028577/305
859はちみつ餃子 ◆8X2XSCHEME
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;
}
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;
}
860デフォルトの名無しさん
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したときだけなぜ判定失敗してくれるのかもう少し考えてみます。
ありがとうございました。
う〜ん、よく分かりませんね。確かに勝手に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したときだけなぜ判定失敗してくれるのかもう少し考えてみます。
ありがとうございました。
861はちみつ餃子 ◆8X2XSCHEME
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 を削るとエラーになるんだよな。
なんだかよくわかんないね。
左辺が曖昧だからかもしれない。
左辺の型を 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 を削るとエラーになるんだよな。
なんだかよくわかんないね。
862デフォルトの名無しさん
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
度々ありがとうございます。再現確認したところ、確かに余計なテンプレート引数が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
863デフォルトの名無しさん
2021/10/25(月) 02:19:56.83ID:LmZJdmU+ 最後のコードは右上の設定ボタンから -std=c++17 を追加することで実行できます。
864デフォルトの名無しさん
2021/10/25(月) 13:57:01.70ID:p1HT8A4i iostreamのシフト演算子オーバーロードは文句を言われてるがrangesのoperator|のオーバーロードはどうなんですかね
865はちみつ餃子 ◆8X2XSCHEME
2021/10/25(月) 14:01:06.87ID:dRHq7DJG 感覚的にはまあ順当だろうと思う。
日付やパスで / を使うのに比べればよっぽど……。
日付やパスで / を使うのに比べればよっぽど……。
866デフォルトの名無しさん
2021/10/25(月) 15:38:37.13ID:x4U5y7kU 組み込みの意味を持たないオーバーロード専用演算子があれば良かったのにな
用意しておかなかったのはC++の初期デザインの失敗だったと思う
用意しておかなかったのはC++の初期デザインの失敗だったと思う
867デフォルトの名無しさん
2021/10/25(月) 16:09:42.75ID:SLeimCOK 意味を持たない演算子が意図せず呼ばれてしまうくらいならコンパイルエラーになったほうがマシでは
868はちみつ餃子 ◆8X2XSCHEME
2021/10/25(月) 17:28:55.78ID:dRHq7DJG ところで Haskell で一定の記号の組み合わせは何でも新しい演算子として定義できる仕組みがある。
!#$%&*+./<=>? あたりとその他 Unicode 内いくらかも含めた組み合わせで演算子を作っていい。
優先順位も決められるし左結合か右結合かも決められる。
事実上無制限に違う字面の演算子を作れるんだよ。
<?+> とか #-. とか <<-~ みたいな演算子が実際に使われてるわけ。
こういう極端なのはさすがにあまりうらやましくはないよな……。
>>866
かといって有限の演算子をある程度に多く用意したところでオーバーロードを許すなら
どこかで全然違う意味で使われることもあるのは避けようがないし、
C++ くらいにスッパリと諦めるのもそれはそれで思い切りが良くて良いと思う。
!#$%&*+./<=>? あたりとその他 Unicode 内いくらかも含めた組み合わせで演算子を作っていい。
優先順位も決められるし左結合か右結合かも決められる。
事実上無制限に違う字面の演算子を作れるんだよ。
<?+> とか #-. とか <<-~ みたいな演算子が実際に使われてるわけ。
こういう極端なのはさすがにあまりうらやましくはないよな……。
>>866
かといって有限の演算子をある程度に多く用意したところでオーバーロードを許すなら
どこかで全然違う意味で使われることもあるのは避けようがないし、
C++ くらいにスッパリと諦めるのもそれはそれで思い切りが良くて良いと思う。
869デフォルトの名無しさん
2021/10/25(月) 17:51:03.08ID:s1VnbLSn 演算子ってのはwellknownだからこそ意味があると思うんだけどな
演算子のオーバーロードもその“意味”から大きく逸脱しないことを求めていたと思うし
意味を持たないオーバーロード専用演算子ってのは
プログラマーによって意味が真逆になりかねないから危険だと思う
そんなことするぐらいなら普通に名前を付けて関数定義したほうがマシに思える
演算子のオーバーロードもその“意味”から大きく逸脱しないことを求めていたと思うし
意味を持たないオーバーロード専用演算子ってのは
プログラマーによって意味が真逆になりかねないから危険だと思う
そんなことするぐらいなら普通に名前を付けて関数定義したほうがマシに思える
870デフォルトの名無しさん
2021/10/25(月) 17:56:20.95ID:5fKOgArh そこら中訳わかんない記号だらけのソースとか悪夢でしかないなw
871デフォルトの名無しさん
2021/10/25(月) 18:04:59.44ID:LmZJdmU+ >>857の原因判明しました。
同一の問題がstackoverflowで解決されていたのでリンクだけ貼っておきます。
https://stackoverflow.com/questions/52845621/cant-stream-stdendl-with-overloaded-operator-for-stdvariant
上記に従った対策コードは以下のとおりです。
https://godbolt.org/z/8e9o3MnaG
同一の問題がstackoverflowで解決されていたのでリンクだけ貼っておきます。
https://stackoverflow.com/questions/52845621/cant-stream-stdendl-with-overloaded-operator-for-stdvariant
上記に従った対策コードは以下のとおりです。
https://godbolt.org/z/8e9o3MnaG
872デフォルトの名無しさん
2021/10/25(月) 20:01:58.87ID:VZsrHh6g >>866
リザーブの演算子持っとけって言いたいんだろうけどこう言う奴はいくつ持ってても足りねーとか言うからw
リザーブの演算子持っとけって言いたいんだろうけどこう言う奴はいくつ持ってても足りねーとか言うからw
873デフォルトの名無しさん
2021/10/25(月) 21:34:55.28ID:3IW01+t9 演算子オーバーロードって自分で書くにはいいけど他人のコードを読むのが地獄だな。
874デフォルトの名無しさん
2021/10/25(月) 21:35:04.23ID:EqTxifVC while (fread(&x, sizeof(double), 1, fin) > 0) {
fprintf(fout, "%5.4f\n", x);
}
こんな風に書くとコベリティ君がfreadは読み込んだバイト数を返すが使っていませんみたいなこと言い出すんだが
は?使ってますけど?みたいな気持ちしかないんだけど
何を求められてるんだろうか。
fprintf(fout, "%5.4f\n", x);
}
こんな風に書くとコベリティ君がfreadは読み込んだバイト数を返すが使っていませんみたいなこと言い出すんだが
は?使ってますけど?みたいな気持ちしかないんだけど
何を求められてるんだろうか。
875デフォルトの名無しさん
2021/10/26(火) 06:12:19.30ID:lDQyydUS >>874
そんなのシノプシスに聞けよ…
そんなのシノプシスに聞けよ…
876デフォルトの名無しさん
2021/10/26(火) 06:48:54.44ID:ch+2e+/f >>870
昔のAPLとかかw
昔のAPLとかかw
877デフォルトの名無しさん
2021/10/26(火) 08:08:42.05ID:a/qQal0X 演算子に限らず、ある関数を特定の名前空間の内部だけ使えるように限定できたっけ?
「あるスコープだけこういう使い方」ならまだ混乱も少ないかね。
「あるスコープだけこういう使い方」ならまだ混乱も少ないかね。
878デフォルトの名無しさん
2021/10/26(火) 08:14:06.41ID:FOkaXEb/ ん? それこそが名前空間の可視性制御だろ
879デフォルトの名無しさん
2021/10/26(火) 08:14:48.16ID:X4knYEql 関数内で構造体を定義し、その中でstatic関数を定義する
880デフォルトの名無しさん
2021/10/26(火) 08:15:27.77ID:X4knYEql あ、違った
class内のprivate関数でいいんじゃね
class内のprivate関数でいいんじゃね
881デフォルトの名無しさん
2021/10/26(火) 08:27:02.14ID:cqUp+YH+882デフォルトの名無しさん
2021/10/26(火) 09:22:33.47ID:tIXOLnPL883デフォルトの名無しさん
2021/10/26(火) 10:05:37.17ID:I5hwU/3x >>874
fprintfはええんか?
fprintfはええんか?
884デフォルトの名無しさん
2021/10/26(火) 10:21:21.31ID:g/XkL0k7 niebloidの出番じゃないの?演算子オーバーロードには使えないが
885デフォルトの名無しさん
2021/10/26(火) 12:31:52.75ID:E+rw0Wy/886デフォルトの名無しさん
2021/10/26(火) 12:54:35.40ID:FaeDWsHu 今日もまた単発IDの曖昧発言onlyですね
887ハノン ◆QZaw55cn4c
2021/10/31(日) 10:43:09.43ID:hT9enBIH テステス
888デフォルトの名無しさん
2021/11/01(月) 17:04:38.20ID:uZUsIwlp std::function を引数にとる関数を作ってるんだが、参照で渡すのとコピーで渡すのでどのように動作が変わるかわからない
参照で渡して良いですか
参照で渡して良いですか
889デフォルトの名無しさん
2021/11/01(月) 17:28:34.89ID:2TKPTRzu std::funcて中身は関数ポインタ―でしょ
コピーで済むものを参照で渡す必要はそもそもないんじゃないの
受け取り先で書き換えて返すなら別だけど
コピーで済むものを参照で渡す必要はそもそもないんじゃないの
受け取り先で書き換えて返すなら別だけど
890はちみつ餃子 ◆8X2XSCHEME
2021/11/01(月) 17:29:06.34ID:w5vOXkrp >>888
「引数にとる」というのは実引数の型も std::function 型という意味?
「引数にとる」というのは実引数の型も std::function 型という意味?
891デフォルトの名無しさん
2021/11/01(月) 17:41:35.71ID:ja4QDiEt892デフォルトの名無しさん
2021/11/01(月) 17:42:17.47ID:P2kjdACs コピーだろー
893デフォルトの名無しさん
2021/11/01(月) 17:54:17.61ID:uZUsIwlp >>890
関数を想定しています
関数を想定しています
894はちみつ餃子 ◆8X2XSCHEME
2021/11/01(月) 17:58:12.22ID:w5vOXkrp >>893
仮引数の側を std::function の参照にしたところで、実引数の側が std::function ではないときは
変換して一時オブジェクトを作ってからその参照をとる形になるんだよ。
これは std::function に限らない一般原則。
どちらにしても新しいオブジェクトを構築するので参照にする意味がない。
仮引数の側を std::function の参照にしたところで、実引数の側が std::function ではないときは
変換して一時オブジェクトを作ってからその参照をとる形になるんだよ。
これは std::function に限らない一般原則。
どちらにしても新しいオブジェクトを構築するので参照にする意味がない。
895デフォルトの名無しさん
2021/11/01(月) 18:35:36.43ID:XqzqlHR8 クラスのメンバーにstd::functionをいくつか用意しておいて、
条件によりどれかのstd::functionを引数に取るprivateなメンバ関数とかなら参照にする意味はあるかもしれないw
条件によりどれかのstd::functionを引数に取るprivateなメンバ関数とかなら参照にする意味はあるかもしれないw
896デフォルトの名無しさん
2021/11/01(月) 19:28:38.40ID:Qg2QcgLf この流れで質問をば。
std::functionだと単体のR opetator()(Arg...)しか指定できないけど、複数のメソッドを指定できるように拡張するにはどうしたらいいかしらん?
継承じゃなくてtype erasure を使ったgeneral smart pointerとでもいうようなやつが欲しいんだけど、どこかに実装ないかなぁ。
std::functionだと単体のR opetator()(Arg...)しか指定できないけど、複数のメソッドを指定できるように拡張するにはどうしたらいいかしらん?
継承じゃなくてtype erasure を使ったgeneral smart pointerとでもいうようなやつが欲しいんだけど、どこかに実装ないかなぁ。
897デフォルトの名無しさん
2021/11/01(月) 19:49:46.26ID:Iw+wFADq anyの使いどころ?
898896
2021/11/01(月) 20:35:42.39ID:0sJcc+2w anyだとメソッドを呼び出せないから機能が足りないですな。
メソッド呼び出しできるインターフェイス付きanyみたいな感じ。
用途は「指定したメソッドがあれば継承関係無しでブチ込める親クラスみたいなanyみたいなshared_ptr」だけど。
メソッド呼び出しできるインターフェイス付きanyみたいな感じ。
用途は「指定したメソッドがあれば継承関係無しでブチ込める親クラスみたいなanyみたいなshared_ptr」だけど。
899デフォルトの名無しさん
2021/11/01(月) 20:39:54.69ID:ja4QDiEt 理解できてないけど普通のテンプレート引数を持つ関数じゃいかんの?
900896
2021/11/01(月) 21:35:17.71ID:0sJcc+2w Haskellの型タイプというのがイメージに近いか。
具体例をだしてみると、
class A { public: string test1() { return string("A1"); }; string test2() { return string("A2"); }; };
class B { public: string test1() { return string("B1"); }; string test2() { return string("B2"); }; };
vector<generic_ptr<string test()>>c;
c.push_back(make_shared<A>());
c.push_back(make_shared<B>());
c[0]->test1(); // A1
c[1]->test1(); // B1
c[0]->test2(); // A2
c[1]->test2(); // B2
みたいに、anyみたいに雑多なオブジェクトをブチ込むけど、
anyとは違ってそのまま共通メソッドを呼び出せるようにする、
というのが狙いね。
具体例をだしてみると、
class A { public: string test1() { return string("A1"); }; string test2() { return string("A2"); }; };
class B { public: string test1() { return string("B1"); }; string test2() { return string("B2"); }; };
vector<generic_ptr<string test()>>c;
c.push_back(make_shared<A>());
c.push_back(make_shared<B>());
c[0]->test1(); // A1
c[1]->test1(); // B1
c[0]->test2(); // A2
c[1]->test2(); // B2
みたいに、anyみたいに雑多なオブジェクトをブチ込むけど、
anyとは違ってそのまま共通メソッドを呼び出せるようにする、
というのが狙いね。
901デフォルトの名無しさん
2021/11/01(月) 22:33:44.83ID:JtJuMIHt902896
2021/11/02(火) 00:28:12.27ID:F29rpsLU >901
ありがとう。こういうのもあるのね
……でも BOOST_TYPE_ERASURE_MEMBER を使ったコンセプトがWandboxで上手く動かないなぁ。
もうちょっと試してみるか。
ありがとう。こういうのもあるのね
……でも BOOST_TYPE_ERASURE_MEMBER を使ったコンセプトがWandboxで上手く動かないなぁ。
もうちょっと試してみるか。
903デフォルトの名無しさん
2021/11/02(火) 10:51:55.89ID:7a5iqwfV std::thread で作られるスレッドって
スタックサイズはデフォルトいくつなん?
変更とかできるん?
スタックサイズはデフォルトいくつなん?
変更とかできるん?
904デフォルトの名無しさん
2021/11/02(火) 10:59:21.25ID:oKrr57AH >>903
スタックなんて概念がないのに制御できるわけがない
スタックなんて概念がないのに制御できるわけがない
905デフォルトの名無しさん
2021/11/02(火) 11:48:47.80ID:LR6fq+wY linuxならulimit -sかpthread_attr_setstacksizeで設定できる
ただ確保されるのは仮想メモリなので現実的にはその設定あんまり使い所がない
そしてC++とか関係ない
ただ確保されるのは仮想メモリなので現実的にはその設定あんまり使い所がない
そしてC++とか関係ない
906デフォルトの名無しさん
2021/11/02(火) 13:09:21.89ID:TehqQXLJ stdよりposixのほうが洗練されてるよな
907デフォルトの名無しさん
2021/11/02(火) 17:28:47.39ID:LR6fq+wY 何いってんの?この人
908デフォルトの名無しさん
2021/11/02(火) 19:04:22.54ID:TehqQXLJ 意味わかんなくてpthread使ってんなら相当頭悪い
909デフォルトの名無しさん
2021/11/02(火) 19:13:49.36ID:U4IKz2Wy むだに喧嘩すんなよ
910デフォルトの名無しさん
2021/11/02(火) 19:28:12.57ID:LR6fq+wY 比較対象がおかしいんだからしょうがなくね?w
911デフォルトの名無しさん
2021/11/05(金) 00:18:59.36ID:2vTbLoUN 基底クラスに定数持たせるけど値は継承先で決めたい。
例)Carクラスには計算に使うが変更はしない定数 weight hight width があり、それは継承した車種クラス毎に異なる、など。
下記でコンパイル通るようですが、定数増えると見づらく、もっとスマートなやり方あったらご教授願いたく。
class Car
{
protected:
const double weight, height, width;
public:
Car(double w, double h, double wd)
: weight(w)
, height(h)
, width(wd)
{}
};
class CarA : public Car
{
CarA() : Car(1000.0, 1.8, 1,8) {}
};
例)Carクラスには計算に使うが変更はしない定数 weight hight width があり、それは継承した車種クラス毎に異なる、など。
下記でコンパイル通るようですが、定数増えると見づらく、もっとスマートなやり方あったらご教授願いたく。
class Car
{
protected:
const double weight, height, width;
public:
Car(double w, double h, double wd)
: weight(w)
, height(h)
, width(wd)
{}
};
class CarA : public Car
{
CarA() : Car(1000.0, 1.8, 1,8) {}
};
912デフォルトの名無しさん
2021/11/05(金) 00:22:58.93ID:O1PLiy99 別に普通だと思うけどどの辺が見づらいと思うんだ?
913はちみつ餃子 ◆8X2XSCHEME
2021/11/05(金) 01:26:19.60ID:8QrXrM3i 値が const であるだけでなく static であって欲しいという意図なんじゃないかと想像する。
914デフォルトの名無しさん
2021/11/05(金) 01:29:07.53ID:zGuhJhpK クラステンプレート化すればいいじゃない
template<double W, double H, double WD>
template<double W, double H, double WD>
915デフォルトの名無しさん
2021/11/05(金) 01:41:20.30ID:gd3zcTPm doubleってテンプレート引数OKになったの?
917デフォルトの名無しさん
2021/11/05(金) 02:25:46.30ID:Xs8oV2Az C++20では普通に使えるかもだけど、引数に名前を付ける風のトリックがあるらしい
https://www.fluentcpp.com/2018/12/14/named-arguments-cpp/
https://www.fluentcpp.com/2018/12/14/named-arguments-cpp/
918デフォルトの名無しさん
2021/11/05(金) 05:55:16.82ID:caWVwyr0919デフォルトの名無しさん
2021/11/05(金) 06:25:31.61ID:8h2e+y9J920デフォルトの名無しさん
2021/11/05(金) 07:38:38.22ID:gd3zcTPm C++20で指示付き初期化が出来るようなので、もしC++20が使えるなら定数を構造体にまとめたらいいかも
https://cpprefjp.github.io/lang/cpp20/designated_initialization.html
https://cpprefjp.github.io/lang/cpp20/designated_initialization.html
921デフォルトの名無しさん
2021/11/05(金) 08:22:45.14ID:OHT8JXtH922デフォルトの名無しさん
2021/11/05(金) 12:38:49.71ID:gSSLx8YQ923デフォルトの名無しさん
2021/11/05(金) 13:46:37.13ID:Xs8oV2Az >>920
C++20で使えるのそれそれ。gccでは元々使えるけど...
C++20で使えるのそれそれ。gccでは元々使えるけど...
924はちみつ餃子 ◆8X2XSCHEME
2021/11/05(金) 13:57:04.43ID:8QrXrM3i >>923
C (C99 以降) には有るからついでに C++ でも使えるようにするのは gcc 的にはたいした手間でもなかったんだろうと思う。
C (C99 以降) には有るからついでに C++ でも使えるようにするのは gcc 的にはたいした手間でもなかったんだろうと思う。
925はちみつ餃子 ◆8X2XSCHEME
2021/11/05(金) 14:01:00.76ID:8QrXrM3i ところで C の designated initializer では配列要素を指示することも出来るんだけど、 C++20 にはこれは入らなかったんだね。
↓ こういうの。
const char *foo[5] = {
[2]="bar"
};
↓ こういうの。
const char *foo[5] = {
[2]="bar"
};
926デフォルトの名無しさん
2021/11/05(金) 14:04:47.27ID:XqgFcDRs c++17以前でも引数を構造体にまとめれば{}で区切って記述できるようになるから多少マシにはなるよね
IntelliSenseが効きにくくなるのが欠点だけど
IntelliSenseが効きにくくなるのが欠点だけど
927デフォルトの名無しさん
2021/11/05(金) 14:10:59.42ID:TiWO+rcp >>922
君は何を言っているんだい?
君は何を言っているんだい?
928デフォルトの名無しさん
2021/11/05(金) 14:27:51.72ID:7LuUsMxr そのCの記述素晴らしいよね
C++的でないのはわかるがどうせ初期化時でしか使わんのだしとっとと入れるべきだった
C++的でないのはわかるがどうせ初期化時でしか使わんのだしとっとと入れるべきだった
929デフォルトの名無しさん
2021/11/05(金) 16:10:31.37ID:gd3zcTPm >>925 ラムダ式のキャプチャと競合するためと書いてるね
930デフォルトの名無しさん
2021/11/07(日) 16:47:32.00ID:qipzvPRM https://ideone.com/d05dJ9
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
#define MAX_SIZE 100
template <class T>
// template <class T, size_t C=MAX_SIZE>
class SizeLimitedAllocator {
public:
typedef T value_type;
using traits = allocator_traits<allocator<T>>;
T *allocate(size_t n) {
if (n > MAX_SIZE) throw bad_alloc();
// if (n > C) throw bad_alloc();
return traits::allocate(_allocator, n);
}
void deallocate(T *p, size_t n) {
traits::deallocate(_allocator, p, n);
}
private:
allocator<T> _allocator;
};
int main()
{
vector<char,SizeLimitedAllocator<char>> vec(MAX_SIZE);
try { vec.resize(MAX_SIZE+1); }
catch (bad_alloc& e) { cerr << e.what() << endl; }
return 0;
}
このコードをコメント側に変更してコンパイルするとこけるんだけど、なんで?
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
#define MAX_SIZE 100
template <class T>
// template <class T, size_t C=MAX_SIZE>
class SizeLimitedAllocator {
public:
typedef T value_type;
using traits = allocator_traits<allocator<T>>;
T *allocate(size_t n) {
if (n > MAX_SIZE) throw bad_alloc();
// if (n > C) throw bad_alloc();
return traits::allocate(_allocator, n);
}
void deallocate(T *p, size_t n) {
traits::deallocate(_allocator, p, n);
}
private:
allocator<T> _allocator;
};
int main()
{
vector<char,SizeLimitedAllocator<char>> vec(MAX_SIZE);
try { vec.resize(MAX_SIZE+1); }
catch (bad_alloc& e) { cerr << e.what() << endl; }
return 0;
}
このコードをコメント側に変更してコンパイルするとこけるんだけど、なんで?
931デフォルトの名無しさん
2021/11/07(日) 17:51:19.26ID:ISiN+sDp >>928
aggregate限定だね
aggregate限定だね
932デフォルトの名無しさん
2021/11/07(日) 17:56:01.13ID:Mdbpk+F7 >>930
https://en.cppreference.com/w/cpp/named_req/Allocator#cite_note-2
> rebind is only optional (provided by std::allocator_traits) if this allocator is a template of the form SomeAllocator<T, Args>, where Args is zero or more additional template type parameters.
これですかね?
カスタムアロケータ自分で定義したことないのでじゃあどうすればいいかは分かりませんが……
https://en.cppreference.com/w/cpp/named_req/Allocator#cite_note-2
> rebind is only optional (provided by std::allocator_traits) if this allocator is a template of the form SomeAllocator<T, Args>, where Args is zero or more additional template type parameters.
これですかね?
カスタムアロケータ自分で定義したことないのでじゃあどうすればいいかは分かりませんが……
933デフォルトの名無しさん
2021/11/07(日) 18:53:11.25ID:Qwz9shRh rebind_allocが悪さしてたりして
934デフォルトの名無しさん
2021/11/07(日) 19:23:12.01ID:A2QjBZsT >>930
SizeLimitedAllocatorの定義にこれ追加すればいいよ
template<typename U>
struct rebind {using other = SizeLimitedAllocator<U,C>;};
SizeLimitedAllocatorの定義にこれ追加すればいいよ
template<typename U>
struct rebind {using other = SizeLimitedAllocator<U,C>;};
935デフォルトの名無しさん
2021/11/08(月) 00:05:22.17ID:dWDs4ee0 https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/ptr_traits.h#L62-L69
この辺の定義にある
定数値という型でないものがテンプレート引数に入ったため、__replace_first_argの下側の定義が使われず
上側の定義が使用されtypeも入らず
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/alloc_traits.h#L80
でrebindできなくなったことが原因でした。
これを回避するためには、>>934のように
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/alloc_traits.h#L51-L57
この下の定義に当てはまるrebind<U>::otherを定義しておく必要があるようです。
定数値でなく型がテンプレート引数に追加された場合は、otherの定義は必要ありませんでした。
この辺の定義にある
定数値という型でないものがテンプレート引数に入ったため、__replace_first_argの下側の定義が使われず
上側の定義が使用されtypeも入らず
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/alloc_traits.h#L80
でrebindできなくなったことが原因でした。
これを回避するためには、>>934のように
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/alloc_traits.h#L51-L57
この下の定義に当てはまるrebind<U>::otherを定義しておく必要があるようです。
定数値でなく型がテンプレート引数に追加された場合は、otherの定義は必要ありませんでした。
レス数が900を超えています。1000を超えると表示できなくなるよ。
ニュース
- 【次の一手】台湾問題で小林よしのり氏が私見「まさに戦争前夜」「ただちに徴兵制を敷いて、高市支持者を最前線へ」… ★2 [BFU★]
- 【速報】日本産牛肉の対中国輸出再開協議が中止 [おっさん友の会★]
- 高市首相答弁を“引き出した”立民・岡田克也氏が改めて説明「なぜ慎重な答弁をされなかったのか。非常に残念に思っている」 ★3 [ぐれ★]
- 【速報】中国、水産物輸入停止と通達 「処理水」理由、日本政府へ ★8 [おっさん友の会★]
- 高市政権「生んだ以上は育てる」 麻生氏 [どどん★]
- 中国側が首相答弁の撤回要求、日本側拒否★8 [夜のけいちゃん★]
- 【高市速報】トヨタ社長、MAGA帽子をかぶって登場し世界を震撼させる [462275543]
- 【実況】博衣こよりのえちえち雑談🧪
- 【高市有事】牛肉の対中輸出再開協議が中止wwwwwwwwwwwwwwww [834922174]
- 中川翔子「みんな、詐欺師には気をつけて!」 [942773469]
- 【👊専】ロケット🚀👊😅👊🚀パーンチww🏡
- 日本人、ついに気づく「あれ、日本が対中国で取れる対抗措置ってなくない…?」 [931948549]
