C++相談室 part162

■ このスレッドは過去ログ倉庫に格納されています
1sage (ワッチョイ fbf0-ofdD)
垢版 |
2022/10/31(月) 14:29:35.57ID:J5sgTSch0
!extend:checked:vvvvv:1000:512
!extend:checked:vvvvv:1000:512
↑同じ内容を3行貼り付けること

次スレは>>980が立てること
無理なら細かく安価指定

※前スレ
C++相談室 part161
https://mevius.5ch.net/test/read.cgi/tech/1653135809/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
2022/12/02(金) 18:31:22.54ID:V13bE4eep
>>458
配列の型によるだろ、嘘教えるなよw
2022/12/02(金) 18:45:28.13ID:tKD1RDkG0
そもそもメモリーアクセスが1クロックでできるかどうかは状況によるしハッシュの計算に150クロック以上とかどこから出てきたんだ?
2022/12/02(金) 18:47:05.45ID:l1cskCXdM
>>459
配列の場合、要素のサイズが任意バイトの場合は、一般には明示的な掛け算が必要だから
1クロックではなかった。
スマソ
462デフォルトの名無しさん (アウアウウー Sa5b-tFPE)
垢版 |
2022/12/02(金) 20:50:07.24ID:mpDpMcgja
シッタカが自爆するスレ
2022/12/02(金) 21:13:31.85ID:7ZxLA8W50
ハッシュはキーがぶつかった時にネストして候補を洗ってく時間がかかるから一意に150クロックってワケでもない
464デフォルトの名無しさん (ワッチョイ d75f-JadS)
垢版 |
2022/12/02(金) 21:26:41.80ID:OAAJQcGw0
Pythonで経過時刻を測る場合、以下のような方法を使いますが
C++でPythonと同じ計測手法を使うにはどうしたら良いですか?

import time
startTime = time.time()
nowTime = time.time() - startTime
print(nowTime)
2022/12/02(金) 21:29:14.69ID:jlYcEgfQp
OSに依るからなぁ
2022/12/02(金) 21:30:36.64ID:RyVNohK20
なんか面倒くさい<chrono>でがんばる
467デフォルトの名無しさん (ワッチョイ d75f-JadS)
垢版 |
2022/12/02(金) 21:33:56.38ID:OAAJQcGw0
>>465
Windows限定で使用する予定です。
2022/12/02(金) 21:36:34.16ID:m95xgUV8M
boost::timer::cpu_timerとか?
2022/12/02(金) 21:41:06.49ID:110d0P8E0
>>467
C++ 関係ないけどパフォーマンスカウンターでggrと良いんでは?
2022/12/02(金) 21:45:16.03ID:FW7hEQSS0
std::time とか?
2022/12/02(金) 21:48:04.00ID:0Xa+fucj0
>>460
全然関係ないんだが
鼻で笑えないのか?
2022/12/02(金) 22:24:02.82ID:eNwFIhhK0
OpenMPの一部であるomp_get_wtime()がじつはパフォーマンスカウンタと同じ精度……

ポータブル……
2022/12/03(土) 00:29:43.64ID:dPKr1JJoM
>>460
keyが10文字の文字列の場合だと大体そんなくらい行くであろうと予想したが、
もうちょっと速い場合もあるかも知れない。
2022/12/03(土) 01:21:25.79ID:dPKr1JJoM
>>463
要は、JSなどで配列とHash法が同じ書き方が出来るが故に、Hash法が
「配列」みたいには高速ではないということを知らない人が居るのではないかと
思って書いただけ。
x86系の場合、配列は、要素サイズが1,2,4,8の時はa[i]がマシン語の1命令で
1クロック、それ以外の一般サイズだと2命令で、今のCPUだと、
4クロック〜20クロック程度。
ハッシュ法だと、keyが10文字の文字列の場合で、最低でも、まあ、100クロック位
はかかると見ておいたほうがいい。最高だと上限は無いが、まあ、数千〜数万
クロック程度になると考えた方がいい。
これは、マシン語まで見たときの常識的な間隔。
2022/12/03(土) 02:42:14.20ID:ngGiofKr0
マシン語の1命令で1クロックって、いつの何のCPUだ
2022/12/03(土) 08:52:01.00ID:+FzzA9JIM
0 以上 64 以下の整数 n に対して 2^n-1 (ビットごとの排他的 OR 演算子ではなく累乗の意味 2**n-1 です)を std::uint64_t 型で返す関数って場合分け無しでスッキリ書けませんかね?
2022/12/03(土) 09:18:16.49ID:riW5om/o0
>>476
こうかな?
std::uint64_t(-1) >> (64-n)
2022/12/03(土) 09:23:14.36ID:qMCuKdke0
std::uint64_tの加算オーバーフロー時の挙動がunsigned intと同様にwrap aroundなんなら普通に
std::uint64_t foo(const int n) { return ((std::int64_t)1 << n) - (std::int64_t)1; }
で良くねconstexpr的な何かとかでマズい?
2022/12/03(土) 09:26:37.99ID:riW5om/o0
すまぬ。 >>477 だと n が 0 のときは未定義なのでそれだけ場合分けが必要になってしまうな。
だからといって (std::uint64_t(1) << n) - 1 だと 64 のときが駄目だし、
場合分け無しという条件だと思ったよりめんどいかも?
2022/12/03(土) 09:43:52.56ID:qMCuKdke0
違った加算オーバーフローの話やなかったorz

シフト演算については
If E1 has an unsigned
type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable
in the result type.
E1 が符号なし型を持つ場合、結果の値は、E1 * 2E2 の、結果の型で表現可能な最大値より 1 大きい値を法とする剰余となる
なので言語規格上は (uint64_t)1 << 64は合法なはず……
2022/12/03(土) 09:49:24.58ID:qMCuKdke0
訂正orz
誤: 2E2
正: 2**E2 (2のE2乗)

符号付きの型はオーバーフローで例外を発生するアーキテクチャーがあるから
表現できるビット数からあふれるコーディングは未定義動作か何かやが
符号無し型はモジュロ演算になるから溢れてもおk
と言う印象(記憶モード
※ 個人の感想です
2022/12/03(土) 10:04:27.89ID:riW5om/o0
>>478
> https://timsong-cpp.github.io/cppwp/n3337/expr.shift
> The behavior is undefined if the right operand is negative, or greater than
> or equal to the length in bits of the promoted left operand.

シフト演算子では右オペランドが (昇格済みの) 左オペランドの幅以上の値だったときは未定義。
2022/12/03(土) 10:15:30.26ID:riW5om/o0
std::bitset を経由すれば大丈夫だということを発見した。

std::uint64_t((compl std::bitset<64>(0)>>(64-n)).to_ullong())

これを「スッキリ」といえるかどうかは微妙なところかもしれぬ……。
2022/12/03(土) 11:26:23.20ID:qMCuKdke0
>>482
わかりた
ではこう汁、
 指数 n == (n/2) + (n/2) + (n & 1) ※ 除算は結果の小数以下切り捨て
ので
 2**n - 1 = 2**((n/2) + (n/2) + (n & 1)) - 1
 = 2**(n/2) * 2**(n/2) * 2**(n&1) - 1
よって
 std::uint64_t foo(const int n) {
  const std::int64_t x = (std::uint64_t)1 << (n / 2);
  return (x * x * ((std::uint64_t)1 << (n & 1)) - (std::int64_t)1;
 }
でだいたいおk、
485デフォルトの名無しさん (ワッチョイ 2647-fbc4)
垢版 |
2022/12/03(土) 11:32:11.79ID:D7LggL4j0
n?1ull<<(n-1):0
2022/12/03(土) 11:45:55.06ID:Xj+KmoE3d
(1llu << (n>>1) << ((n+1)>>1)) - 1
2022/12/03(土) 11:53:09.20ID:Xj+KmoE3d
constexpr uint64_t TABLE[65] = {
0x0000000000000000,
0x0000000000000001,
0x0000000000000003,
...
0xffffffffffffffff
};

return TABLE[n];
2022/12/03(土) 11:57:41.15ID:Xj+KmoE3d
x86-64の場合
shl reg, clのclは下位6bitしか見ないから
1ull<<nが正しく動いた場合マシン語レベルでは分岐してることになる
2022/12/03(土) 21:09:42.26ID:WYd/d9iJ0
>>457
今さら知らなかったとは言えなくて
元々知ってた別人になるしかないもんな

それほどまでに恥ずかしいことだからw

# さあ、おまえが別人かどうかの判断は衆目に任せよう
2022/12/03(土) 23:32:15.77ID:qMCuKdke0
(ID:Xj+KmoE3d が天才すぎてつらいので埋め)
2022/12/03(土) 23:46:07.24ID:mCv82Mp+M
ところで、C++でも、Javab磴#でも、メモャ梶[不足例外を封竭ォしない風潮bノなっている
ようです。それは、メモリー不足が起きる可能性があるところの、
文字列合成やコンテナ要素追加が簡単に書けるようになった反面、
その全ての箇所でエラー処理をするのはめんどくさすぎるという
事情から来ていると思います。
しかし、テキスとエディタなどで、一文字や一行追加した時にメモリーが確保できない
場合に、「メモリーが一杯です」などと表示することはMS-DOSならよくあったことで、
そのような場合にメモリー不足例外を補足する事は原理的には可能です。
いまや、そのような場合のメモリー不足はほぼ起き得なくなってますが、エラーを感知
しないで本当に良いと思われますか?
もっと進めれば、メモリー不足例外は、商用アプリでも「完全無視」を決め込んでも良いと
思われますか?
2022/12/03(土) 23:47:44.27ID:mCv82Mp+M
>>491
携帯SIMを使っているので電波にエラーが生じたらしいです:
誤:ところで、C++でも、Javab磴#でも、メモャ梶[不足例外を封竭ォしない風潮bノなっている
正:ところで、C++でも、JavaやC#でも、メモリ不足例外を補足しない風潮になっている
2022/12/04(日) 00:02:09.11ID:r/mQBEYb0
>エラーを感知 しないで本当に良いと思われますか?
良い
どうせメモリ不足になったら有効なことはほとんど何もできない

ただしそのかわり処理の不意の中断から絶対に保護すべきリソースとか絶対動かしたままにしてはいけない処理は
例外安全なクラスで管理して確実にクローズ処理せねばならない

jこれはメモリ不足の状況でも同じで、そういうのはヒープを使わないで書くのが最善やが、
内部でヒープを使うライブラリに依存している等でヒープをどうしても使わざるおえないの場合は
事前malloc()→例外捕捉時に解放、というテクが昔からあっる
2022/12/04(日) 00:02:21.62ID:BcAMllhiM
スタック的な(?)コンテナで、pop_back()メソッドは戻り値が void型で、
つまり、pop したデータを返しませんが、BJ. stroustrup氏によれば、
それもreturn文で要素をコピー(?)する際に、メモリー不足例外が起きる
可能性考慮したとのことです。
どうしてmoveじゃ駄目なのかもし分かりませんでしたが。
2022/12/04(日) 00:04:34.95ID:BcAMllhiM
>>493
>どうせメモリ不足になったら有効なことはほとんど何もできない
MS-DOSの時、テキストエディタなどではメモリー不足になると、
ちゃんとメッセージを出して、なおかつ、その後もメモリーが無い割には
安定動作してました。
2022/12/04(日) 00:11:51.06ID:S/+N28Tr0
>>489
まだ粘着してるのかよ...
本人だと思いたいんならそれでいいんじゃね?
おれが本人かどうかに関わらずお前が>>231で本人が謝ってるのにしつこく>>227に粘着するクズであることは確定したし
まあもうそうするしかないんだろうけどw
2022/12/04(日) 00:17:03.45ID:r/mQBEYb0
>>494
x = queue.pop();
というのを許すキューの仕様だと
とキュー上のx'とそのコピーxが同時に存在するタイミングが一瞬生じてメモリ不足になりかねないという>>494の懸念の他に、
コピコンが呼ばれる時間の無駄がある

xにムーブコンストラが定義してありqueue.pop()をムーブ対応に設計したとしても
ムーブコンストラクタが呼ばれる時間の無駄は相変わらず存在する

最も効率が良いのはpop()するタイミングまでキュー上のオブジェクトの参照を返し、
pop()するタイミングではキュー上のオブジェクトの破棄のみ行うという現行のインターフェース、
2022/12/04(日) 00:20:25.80ID:r/mQBEYb0
>>495
おま環、
2022/12/04(日) 00:31:29.29ID:BcAMllhiM
>>497
>x = queue.pop();
>というのを許すキューの仕様だと
>とキュー上のx'とそのコピーxが同時に存在するタイミングが一瞬生じてメモリ不足になりかねないという
よく分かりません。できればもっと詳しくお願いできませんか。
キュー上の x' を x に move すれば駄目なのでしょうか?

>xにムーブコンストラが定義してありqueue.pop()をムーブ対応に設計したとしても
>ムーブコンストラクタが呼ばれる時間の無駄は相変わらず存在する
>最も効率が良いのはpop()するタイミングまでキュー上のオブジェクトの参照を返し、
>pop()するタイミングではキュー上のオブジェクトの破棄のみ行うという現行のインターフェース、

なるほど、参照で返すのは効率がよいのは分かりますが、stroustrup氏によれば、moveは
速いと主張されているわけです。
私はmoveより参照の方が効率が良いと常々思っておりましたが。
彼はmoveが大好きなはずなのですが。
2022/12/04(日) 00:37:44.43ID:r/mQBEYb0
>>499
>キュー上の x' を x に move すれば駄目なのでしょうか?
ムーブコンストラが呼ばれる時間の無駄がある(2回目
2022/12/04(日) 00:41:37.02ID:BcAMllhiM
>>500
>ムーブコンストラが呼ばれる時間の無駄がある(2回目
なるほど、ならば、スタックポインタだけ元に戻して、値は捨ててしまう
バージョンの pop を用意すれば良いだけでは無いですか、今みたいに。
2022/12/04(日) 00:43:51.82ID:BcAMllhiM
>>501
Strousstrup氏によると、メモリー不足になって例外が生じた場合の
対処が難しい、みたいなことを言っていたと思います。
しかし、moveコンストラクタ/代入を使った場合にはメモリー不足も生じませんし、
moveコンストラクタ/代入は例外を生じさせてはいけない、と彼自身は
普段から何度も言及していたと思うんです。
2022/12/04(日) 00:49:09.96ID:BcAMllhiM
>>502
仮にstackの要素クラスにコピーコンストラクタしかない場合は、メモリー不足が
生じてstd::bad_alloc 例外がthrowされる場合があるとは思いますが、難しい
とは言ってもそれが生じた場合に対処が全く出来ないとは思えません。
あるとすれば、要素がmoveコンストラクタを持っている場合でも、
try catch ブロックを書くことで、オーバーヘッドが生じる
場合があることを彼は恐れていたのでしょうか。
2022/12/04(日) 01:11:37.29ID:r/mQBEYb0
>>501
ムーブしたかったらqueue.front()が返す参照でキュー上のx'をxか何かにムーブするだけ(※1)で良くね↑?
 x = std::move(queue.front());
 queue.pop_front();

※1: xやx'のクラスにムーブコンストラの定義は必要

>スタックポインタだけ元に戻して、値は捨ててしまう
>バージョンの pop を用意すれば良いだけでは無いですか、今みたいに。
ムーブするpop_front()と、デストラクタを呼ぶだけの今のpop_front()がどこが同じなのかkwsk、
2022/12/04(日) 01:20:22.79ID:qWdYVkpM0
標準例外安全規則と強い保証がどうのこうの
2022/12/04(日) 01:33:30.77ID:BcAMllhiM
>>504
マシン語の「pop命令」は伝統的に、スタックポインタを戻すことと、値を読み出すことを
同時に行っていました。
C++の設計では、値の読み出しと、スタックポインタを戻すことが分かれており、命名も
変なのです。
つまり、2つの事を合体させて行なうのが伝統的に「pop」であった伝統や習慣とは
異なる命名をC++はとってしまっているので、心理的に受け入れがたくなっているわけです。
2022/12/04(日) 01:50:30.99ID:BcAMllhiM
>>506
例えば、Rustのpopは、ちゃんとマシン語の伝統と同じく、
戻り値が読み出された値になっていて、かつ、スタックポインタも戻ります。
C++のはどうしてこうなったのか、と思うように伝統を破ってます。
伝統を知らない人が作ったかのように。
2022/12/04(日) 02:00:59.03ID:6yRfEQxP0
削除と値返却を同時にやるpop()が例外安全的に糞だって話はExceptionalC++に1章割いて載ってたはず
今手元にないけど
2022/12/04(日) 02:03:07.32ID:qWdYVkpM0
C++だけでなく、いくつかの言語で、配列にアクセスするのに
push() pop() といった名前の関数があるから、その流れじゃないの
対象はあくまでも配列であって、cpu のスタックとは色々異なるわけだし
そこでどこまでスタックぽく扱うかは、言語の仕様というか設計者のお好みによるというかw
2022/12/04(日) 02:10:09.58ID:BcAMllhiM
>>508
その辺の話をここに書いていただけると幸いです。
2022/12/04(日) 02:22:20.52ID:BcAMllhiM
>>510
自己レスですが、
https://stackoverflow.com/questions/25035691/why-doesnt-stdqueuepop-return-value
これですかね。
[Q] Why doesn't std::queue::pop return value.?
[A]
・・・
So, whats the difference, pop function could have done the same thing.

It could indeed have done the same thing. The reason it didn't, is because a pop that returned the popped element is unsafe in the presence of exceptions (having to return by value and thus creating a copy).

Consider this scenario (with a naive/made up pop implementation, to ilustrate my point):

template<class T>
class queue {
T* elements;
std::size_t top_position;
// stuff here
T pop()
{
auto x = elements[top_position];
// TODO: call destructor for elements[top_position] here
--top_position; // alter queue state here
return x; // calls T(const T&) which may throw
}
If the copy constructor of T throws on return, you have already altered the state of the queue (top_position in my naive implementation) and the element is removed from the queue (and not returned). For all intents and purposes (no matter how you catch the exception in client code) the element at the top of the queue is lost.

This implementation is also inefficient in the case when you do not need the popped value (i.e. it creates a copy of the element that nobody will use).

This can be implemented safely and efficiently, with two separate operations (void pop and const T& front()).
2022/12/04(日) 10:36:33.77ID:9l16UriTd
MMミネヲからはperlerの臭いがする
2022/12/04(日) 11:36:02.70ID:flilPTWf0
0〜255しか格納されないことが保証されている変数aがあって
その変数の値を以下のイメージのように判定する効率的なやり方はないでしょうか
a == {8, 9, 12}
aが{ }内のいずれかの値に該当しているかどうかを判定したいです
{ }はあらかじめ定数でもよいです
2022/12/04(日) 11:40:31.47ID:RAGda7mP0
set<int> unko { 8, 9, 12};
if(unko.find(a) != unko.end()) goto hell;
2022/12/04(日) 11:44:07.96ID:AOlAqVGT0
ルックアップテーブル
2022/12/04(日) 11:54:47.89ID:flilPTWf0
>>514
>>515
ありがとうございます
アドバイスから、bool型の配列を用意しておいてaを添え字にすればよいと思いました
517デフォルトの名無しさん (ワッチョイ c001-g9pY)
垢版 |
2022/12/04(日) 12:07:00.75ID:JyCGAu5J0
std::bitset<256>はどうですか?
2022/12/04(日) 16:18:10.81ID:RV2/jwt7M
>>513
BYTE qqq[256] = {};
void init() {
 qqq[8]=1;
 qqq[9]=1;
 qqq[12]=1;
}

inline BOOL IsInQqq(int a)
{
 return qqq[a];
}
2022/12/04(日) 16:45:55.42ID:RAGda7mP0
inline bool is_8_9_12(uint8_t a)
{
return 0b0001'0011'0000'0000 & 1 << a;
}
2022/12/04(日) 17:30:39.25ID:flilPTWf0
いろいろ例をありがとうございます
pascalからの移行で集合型をどうにか再現できないかと試している中での質問でした
pascalの集合型なら[8, 9, 12](8, 9, 12は一例で、本来は任意の値を指定したい)を
直接使えて便利なので多用していました

アドバイスのおかげで比較は近いことを再現できましたが、
それとは別のケースで[8, 9, 12]を直接関数の引数で指定する方法を探しています
引数で指定する際の値の範囲は0〜31を超えることはなさそうなので
ビットを立てた整数を返す、可変長引数を取る関数を作れば良さそうだと思いました
2022/12/04(日) 17:37:18.99ID:S/+N28Tr0
>>520
> 集合型をどうにか再現
それが>>517じゃねーの?

> ビットを立てた整数を返す、可変長引数を取る関数を作れば良さそうだと思いました
そういう関数を作れば良さそうだと思います
2022/12/04(日) 17:49:59.78ID:flilPTWf0
std::bitset<256>も試してみましたが
{8, 9, 12} こういった形式単独で使えるやり方はないかと調べていました
2022/12/04(日) 18:04:56.88ID:YO7rrhiC0
std::bitset は unsigned long long を受け取るコンストラクタには constexpr が付いてるので
それより小さいビット数の bitset についてならコンパイル時に計算してしまうことも出来る。
2022/12/04(日) 18:39:41.91ID:YO7rrhiC0
たぶんやりたいのはこういう感じかな。 (想定は C++17 以上)

#include <bitset>
#include <cassert>
#include <climits>
#include <cstddef>
#include <type_traits>

template <std::size_t N = sizeof(unsigned long long int) * CHAR_BIT, class... T>
constexpr std::enable_if_t<(sizeof...(T) <= N), std::bitset<N>>
make_flagged_bitset(T... args) noexcept {
return std::bitset<N>(((1ULL << args) | ...));
}

// 使用例
int main(void) {
constexpr auto table = make_flagged_bitset(8, 9, 12);
// セットしてないところは偽値
assert(table[0] == false);
assert(table[1] == false);
assert(table[10] == false);
assert(table[20] == false);
// セットしているところは真値
assert(table[8] == true);
assert(table[9] == true);
assert(table[12] == true);
}
2022/12/04(日) 19:19:16.77ID:flilPTWf0
>>524
やりたいことのイメージにすごく近いです
思いもつかない難しい構文で勉強になります
内容を理解して使わせていただきます
ありがとうございました
2022/12/04(日) 19:57:57.00ID:/CRfCGQ0a
定数でいいならマクロでやるとか
#include <cstdio>
#define _(i) (1 << i)
int main() {
int b = _(8) | _(9) | _(12);
for (int i = 0; i <= 12; i++) {
printf("%d:%d\n", i, (b >> i) & 1);
}
return 0;
}
2022/12/04(日) 20:05:21.16ID:YO7rrhiC0
>>525
念のために繰り返すけど >>524>>523 で述べた性質があるので 64 までしか保証されないし、
エラーチェックをあまり頑張ってないので使い方を間違えたときに捕捉されないかもしれない。
あくまでもおおざっぱにはこういう考えかたでいけるだろうというサンプルだからそのつもりで。
2022/12/04(日) 20:59:12.00ID:/CRfCGQ0a
訂正
#define _(i) (1 << i)
より
#define _(i) (1 << (i))
のほうが安心
2022/12/04(日) 23:12:00.77ID:flilPTWf0
これまでビット演算を意識したことがなかったので考え方を知れて助かります
提示いただいた例から自分でも調査が進められそうでなんとかなりそうです
いろいろありがとうございました
2022/12/05(月) 01:35:26.13ID:gMitSG4kM
>>529
ビット演算より、速度は、>>518が一番速いかも。
2022/12/05(月) 10:23:03.76ID:DqBKeem4M
一々メモリアクセスが発生して直感的には遅そうだけど
2022/12/05(月) 10:35:35.88ID:hYIKK9DOp
オプティマイズされるからなぁ
記述だけで速度なんか分からないよ
2022/12/05(月) 11:26:10.51ID:9YGPhFSH0
多分>>526が一番速いと思う
b と i がレジスタに乗れば最近のプロセッサーならシフトは1クロックだし
>>524は最適化が上手く行けば同じ位になりそう
2022/12/05(月) 12:04:38.42ID:AHxKL62Z0
俺なら3クロックでイッちゃうけどね
2022/12/05(月) 13:51:14.89ID:0xhTnbB50
速度重視なら>>518だろ
メモリ食うけど、つーてもキロバイト未満だし
古いワンチップマイコンとかじゃなきゃ微々たるもん
ハードできる人ならワイヤードロジックって手もある
2022/12/05(月) 13:53:40.80ID:iLlZW1brp
速度重視ならアセンブラ…

いや、何でも無い
2022/12/05(月) 14:04:07.58ID:0Re98eJO0
(Cだけど)昔は isalpha や is~ 系のやつはテーブル参照で実装してたのがあった
2022/12/05(月) 14:25:03.89ID:6Xcp09rU0
集合を扱うには std::set を使うのが楽だと思う。
集合を集合っぽく扱える機能は一通りそろってるからたぶん集合型というものに期待していることはだいたい含まれるよ。
Pascal の集合型のことはよう知らんけど。

(一般的に) std::set は二分木で実装されるという都合上、やりたいことによっては性能 (速度) 上の不満が生じることもあるかもしれないけど、
具体的な問題が出る前に先回りして考えてもだいたい徒労だしな。

>>537
実行時にロケールを切り替える必要性からじゃない?
2022/12/05(月) 14:43:13.12ID:9YGPhFSH0
>>537
今でもそうじゃないの?
>>520 > 引数で指定する際の値の範囲は0~31を超えることはなさそうなので
と言う条件だからビット演算の方が早いかもって話であって 、-1~255の範囲ならたいていの環境でテーブル引くのが最速だと思う
2022/12/05(月) 14:45:20.89ID:oclBynCfd
>>535
テーブル参照はキャッシュが絡むから
単純ではない
2022/12/05(月) 15:16:20.05ID:jV16hsjJ0
0〜255を格納する方は定数でしか使わないので>>518のやり方にしました
0〜31くらいまでしか使わない方は、変数に格納された任意の値の集合を
そのまま引数に渡したり、積集合や差集合を求めるのを想定しています

確かにstd::setがその用途ですね
速度が遅そうで敬遠していましたが、実際にはこれがボトルネックになることはないと思います
initializer_listと合わせれば、ほぼPascalと同じ使用感でいけるので、ビット演算のテクニックは
引き続き研究しつつ、いったんstd::setで実装しようと思います
2022/12/05(月) 15:31:21.47ID:0xhTnbB50
>>540
constexprも絡むね
2022/12/05(月) 17:26:36.58ID:rfCFGpMmM
>>540
キャッシュの話になると本当の速さがなかなか分からなくなってくる。
(CPUアーキテクチャやその他の処理の仕方に依存してしまうし。)
キャッシュがある CPU において、キャッシュミスが発生した場合は、
>>526の方が速いであろうと予測はされる。

そもそも、キャッシュの働きが弱いラズパイPICO、Arduino、ESP32 などでは
恐らく>>518 の方が速い。
そもそもシフト演算がシフト量に比例して遅くなるマイコンもあるだろうし。
Z80や8086はそうだった。

x86、x64の場合、
この関数を使うループの中で、他の目的のためにメモリーを大規模に使った場合は、
>>526の方が速いが、沢山メモリーを使わなかった場合は、>>518の方が速い。
2022/12/05(月) 17:29:22.78ID:jV16hsjJ0
std::setは集合演算が思った使い勝手ではなかったです
>>526と列挙型を組み合わせることにしました
長々とスレを消費し申し訳ありませんでした
どのレスも参考になり助かりました
2022/12/05(月) 18:42:52.30ID:6Xcp09rU0
>>544
イテレータを受け渡すのがめんどいな。
そのへんは適当なラッパー関数 (または演算子オーバーロード) を定義すればいいんでないの。
たぶんこんな感じにしたいのかな?
https://wandbox.org/permlink/kpYoEhyGaykqITEG
2022/12/05(月) 18:43:23.85ID:k8gztHb50
>>544
> std::setは集合演算が思った使い勝手ではなかったです
詳しく。
2022/12/05(月) 18:56:45.80ID:k8gztHb50
>>545 なるほどめんどくさいな。
よく考えたら contains すら C++20 からっていうのもひどい話よな。
2022/12/05(月) 20:18:26.80ID:Rd1Rhxq6a
江添が女性支援に批判的で笑ったわ
2022/12/05(月) 20:57:35.77ID:jV16hsjJ0
>>545
ありがとうございます
いろいろ知識や考えが足りませんでした
おかげ様で理想形に近づけることができました

std::set<T> operator*(const std::set<T>& x, std::initializer_list<T> init)
foo * _(1, 3, 5)
https://wandbox.org/permlink/14GBm1DqQ6iUaRPq
2022/12/06(火) 09:26:29.57ID:S4cyJC5Ur
>>548
ツイフェミに批判的なだけだったわ
2022/12/06(火) 09:51:28.64ID:mFLMdD4Ga
まあ、「ザ・男」ってタイプだからな
ケチがディテールにこだわるのもありがち
2022/12/06(火) 11:12:56.86ID:63yxghiR0
今や絶滅危惧種となったテキトーこくの嫌いな人
2022/12/06(火) 13:12:15.09ID:9i6eYS/u0
そういう人ここは比較的多いでしょ?
2022/12/06(火) 13:47:59.27ID:63yxghiR0
配列がハッシュだなんて裏も取らずに信じちまうやつもか?
2022/12/06(火) 14:38:33.85ID:mFLMdD4Ga
テーブルのアクセスに使う添字はインデックス?キー?
2022/12/06(火) 14:47:42.28ID:iX2JPZR5d
サブスクリプト
2022/12/06(火) 15:21:19.75ID:RihiShBFa
>>554
まだいたのかよ、よほど悔しかったんだなw
2022/12/06(火) 15:50:10.05ID:iX2JPZR5d
信じてたやつが返事してるな
今度こそ別人ではあるまい
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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