C++相談室 part145

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2019/09/13(金) 17:13:24.60ID:/ygW08Jq
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part144
https://mevius.5ch.net/test/read.cgi/tech/1563769115/

このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
https://mevius.5ch.net/test/read.cgi/tech/1556142878/

■長いソースを貼るときはここへ。■
 http://codepad.org/
 https://ideone.com/

[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)

----- テンプレ ここまで -----
2019/10/04(金) 12:36:35.66ID:cK/f4a5x
>>312
ありがとうございます!
やってみます
2019/10/04(金) 12:41:17.15ID:G1/ISgxb
c++って文法に曖昧さがないことどうやって保証してんだろ
形式的なアプローチ無理だと思うんだが
2019/10/04(金) 13:05:22.64ID:MVQV/kgg
いや、そんな保証は端っから諦めてるだろ
引数なしの関数宣言とデフォコン呼び出しの曖昧さなんか
長年放置してたのをC++11でようやく対応したし
関数ポインタにキャストするoperatorはtypedef使えとか
言語としての完全性なんか重視してない
2019/10/04(金) 13:28:40.80ID:FzFdUbJu
>>319
曖昧さはあるといわれています。例えば、CPersonというクラスがあったとき、関数内で
CPerson person();
と書いた場合、person という名前で、戻り値の型が CPerson の関数のプロトタイプ宣言なのか、
CPerson クラスの person という変数名(オブジェクト名)の定義なのかの曖昧さがあります。
後者は、CPerson person("name", 25, MALE); などと同じ系統で、実引数が全く無い場合
に相当します。
また、template class の場合に、
A<B<・・・>>
と書くと、>> が右シフト演算子に解釈されてしまうので、回避するために空白を1つ入れて
A<B<・・・> >
としなければならなかった(過去形)時代も有ります。
しかし、パーサーを作る側からすれば、">>" を ">" 2個 だと解釈するのはかなり大変な
労力が必要でです。

また、x < y を比較演算のつもりで A< x < y > などと書くと、A<・・・>
の中に x という template class 名に対しての x<y> が入っていると解釈
されてしまい、> が足りないというエラーになるかもしれません。
回避するには、
A< (x < y) >
と書くと良いと思われます。
2019/10/04(金) 14:48:30.02ID:D8qarNFk
C++というより3Dプログラミングの質問で申し訳ないのだけど、
行列ライブラリglmの以下のコードがbugってる気がするので詳しい人がいたら確認して欲しい。

template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> rotate(qua<T, Q> const& q, T const& angle, vec<3, T, Q> const& v)
{
vec<3, T, Q> Tmp = v;

// Axis of rotation must be normalised
T len = glm::length(Tmp);
if(abs(len - static_cast<T>(1)) > static_cast<T>(0.001))
{
T oneOverLen = static_cast<T>(1) / len;
Tmp.x *= oneOverLen;
Tmp.y *= oneOverLen;
Tmp.z *= oneOverLen;
}

T const AngleRad(angle);
T const Sin = sin(AngleRad * static_cast<T>(0.5));

return q * qua<T, Q>(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin);
}

クオータニオンqをベクタ軸v周りにAngleRad回転させる関数のソースらしいんだが、
最後の行掛け算の順番が逆のような気がする。
qua<T,Q>(...) * qが正解だと思うんだ。

glmはファイル構成がバージョン間で結構派手に変更されてるんで、
最近のバージョンではext/quaternion_transform.inlに上のコードが含まれてる。
古いバージョンではgtx/quaternion.inlにあったような気がする。
2019/10/04(金) 14:55:11.92ID:FzFdUbJu
>>322
あるライブラリでのq1 * q2 という書き方が、q2 * q1
がどういう意味に解釈されるかは、
2019/10/04(金) 15:01:05.28ID:FzFdUbJu
>>322
(>>323 は誤投です。)
あるライブラリでの q1 * q2 という書き方が、別のライブラリでは
q2 * q1 と等価なことが有り得て、それはベクトルや行列計算全般に
言える記法の違いなのでこのソースだけではなんとも言えない。
ベクトルの場合、成分表示を1列の縦行列と考えるか1行の横行列
と考えるかによって、賭け全の左右が逆さまになる。
その結果、成分表示で書かない表記も、左右どちらかで書くかは
好みの問題となる。
特に Quaternion の場合も同様。
2019/10/04(金) 15:02:02.33ID:FzFdUbJu
>>324
誤:と考えるかによって、賭け全の左右が逆さまになる。
正:と考えるかによって、掛け算の左右が逆さまになる。
2019/10/04(金) 15:45:42.88ID:P4b1n6up
OpenGL系は縦ベクトルだね
D3Dを前提にしたライブラリとは逆になる(行列も転置
2019/10/04(金) 15:58:00.91ID:FzFdUbJu
>>326
数学や物理学では縦ベクトルが多いが、D3Dはそれに従ってない。
328デフォルトの名無しさん
垢版 |
2019/10/04(金) 16:08:07.51ID:JXWhYfPM
テンプレが糞だと思う瞬間はいくつもあるが
その一つはネストしてるときの閉じ括弧
>> じゃだめで > > ってわざわざ分けないといかんうざい
2019/10/04(金) 16:08:35.30ID:P4b1n6up
>数学や物理学では縦ベクトルが多いが、D3Dはそれに従ってない。
みたいだね
D3Dからそれ以外に移るとみんなここで引っかかるけど
実は行列周りは(大文字は行列として)
OpenGLに合わせるとA*B*C*xとなるのを
D3Dではx*C*B*Aと書けた方が、左からの計算が全部結果がベクトルなので計算量が減るというメリットはある
MSはC++での書きやすさと効率を考えたのかもしれない
330デフォルトの名無しさん
垢版 |
2019/10/04(金) 16:09:02.58ID:JXWhYfPM
>>326-327
縦横ってより右から掛けるか左から掛けるかだと思ってた
意味は一緒なんだろうけど
2019/10/04(金) 16:11:58.82ID:P4b1n6up
>>328
C++11からは連続して書けるようになったで
2019/10/04(金) 16:14:31.61ID:MVQV/kgg
C++03いやC++98?のまま更新止まってるやつ
俺が想像するより遙かに多いのかもしかして

もうC++11でさえ要注意な旧規格になってるんだが
333デフォルトの名無しさん
垢版 |
2019/10/04(金) 16:16:30.52ID:JXWhYfPM
>>329
メモリ上の順序も変わるぞ
SIMDとかで計算されるときの効率にも影響する
必ずしもD3D(横ベクトル方式)が高速化に都合が良いとは言えないんじゃないか

行列の各要素のメモリ上の並びって
glの行列AとD3Dの行列A'はいちいち転置しなくても結局同じになるんだっけ
2019/10/04(金) 16:22:07.03ID:P4b1n6up
ああ確かにメモリの中身は同じだった
格納方式も違うから結果的に同じになるんだよね
そこが余計ややこしい
2019/10/04(金) 16:29:39.34ID:FzFdUbJu
>>329
行列計算は、縦ベクトル方式、横ベクトル方式でも、(それぞれで)「結合則」があるので、
A*B*C*x = A*(B*(C*x))
でもあり、
A*B*C*x = ((A*B)*C)*x)
でもあり、どっちで計算しても結果は同じになる。

また、3D計算の場合、点の座標がいくつあっても、行列を一度計算しておくと、
使いまわしできるので、先に行列の方を計算しておいて、最後に座標の変換
を行うと、点が2個以上あるときには効率が高い。
2019/10/04(金) 16:31:49.50ID:FzFdUbJu
>>332
C++98くらいから、実際問題上使いたくない機能ばかりが追加されるような
傾向があったのに、Upgrade 版は適用外になったりしたりして買う機を逃した。
2019/10/04(金) 16:38:53.10ID:FzFdUbJu
>>329
>MSはC++での書きやすさと効率を考えたのかもしれない
>>335 に既に書いたけど、OpenGL 形式でも、右結合でも、
左結合でも、好きな方で計算は出来る。だから、行列部分を
先に計算しても良いし、座標部分から計算しても良い。
座標部分から計算していくと一見計算量が減るように思える
かも知れないが、点の個数が多くなると、一度だけ行列部分の
積を予め計算しておいて、その結果を全ての点の変換部分に
遣うと効率が劇的に向上するので、むしろ、効率が良いのは逆。
2019/10/04(金) 16:40:53.55ID:P4b1n6up
>>335
確かに(OpenGLでも上で書いたような式が使えるライブラリ使うとして)括弧でくくったりして優先順位変えればいいし
言う通り行列はまとめればいいんだけど
どちらにもメリットデメリットあると言いたかった
2019/10/04(金) 16:51:20.07ID:FzFdUbJu
>>338
実は、アメリカで有名な 3D Graphics の本が、横ベクトル方式を採用していた
事が関係しているかもしれない。要はその本が数学や物理の標準とは何故か
逆の記法を採用していたということ。
340デフォルトの名無しさん
垢版 |
2019/10/04(金) 17:00:49.77ID:FW+Y/3wm
>>337
GL
(A*B*C)*(x0(縦),x1(縦),x2(縦),x3(縦), ... , xN(縦))(横)
D3D
(x0(横),x1(横),x2(横),x3(横), ... , xN(横))(縦)*(C*B*A)
が最速やね
2019/10/04(金) 19:54:25.76ID:5CiM54x6
>>335
行列って結合則は約束されてましたっけ?
2019/10/04(金) 20:17:27.71ID:gZky9oRw
当たり前だろ。
そんなレベルの知識しかないからフォントライブラリ書けないんだよ
2019/10/04(金) 20:27:59.81ID:5CiM54x6
>>342
では証明してください(キリッ)
2019/10/04(金) 21:24:32.75ID:FzFdUbJu
>>343
ベクトル部分はおいておくとして、まず正方行列の部分だけに限定すれば
A(BC)=(AB)C  ・・・(1)
が証明できれば どんな場合でも結合側が成り立つことが数学的帰納法で
証明できます。なので、A,B,C が正方行列の時に(1)を証明すれば全体の証明が
ほぼ終わります。
【(1)の証明】
行列の積の定義により
 (AB)ij=Σ_{k=1}^n A_{ik} B_{kj}  ・・・(2)
です。なので、
{(AB)C}mn = Σ_l(AB)_{ml}C_{ln}
     = Σ_k Σ_l A_{mk} B_{kl} C_{ln} ・・・(3)
です。全く同様に、
{A(BC)}mn = Σ_k A_{mk} (BC)_{kn}
     = Σ_k A_{mk} Σ_l B_{kl} C_{ln}
     = Σ_k Σ_l A_{mk} B_{kl} C_{ln} ・・・(4)
となり、(3), (4) が一致することから、
 {A(BC)}mn = {(AB)C}mn
が言えます。これが (1) に他なりません。    (Q.E.D)

次に、このように3つの行列の場合ではなく、一般の個数の行列の場合、
最初に書いたように数学的帰納法を使います。それは、あなた自身で
お考えください。考える力の練習になります。
2019/10/04(金) 22:10:52.87ID:cDY60lSZ
doubleの値を++aした時にaの値は+1と規定されてる?
2019/10/04(金) 23:19:26.96ID:FzFdUbJu
>>345
boolen型以外では、++x は正確に x+=1 と等価です。
x+=1 は、正確に x = x + 1 と等価です。x がポインタ型の場合は、
BYTE 単位で見ると object size 単位で増加しますが、double/float/int/short/char
などの「算術型」の場合は、単純に 1 が足されるだけです。


https://en.cppreference.com/w/cpp/language/operator_incdec
For non-boolean operands, the expression ++x is exactly equivalent to x += 1, and the expression --x is exactly equivalent to x -= 1, that is, the prefix increment or decrement is an lvalue expression that identifies the modified operand.
347デフォルトの名無しさん
垢版 |
2019/10/04(金) 23:36:52.32ID:NJj/Utu/
>>346
ありがとうございます。
という事はキャストの時におかしくなっているのかな?

aの値は0.0〜100.0程度
for(double i = a; i < 1000.0; ++i){
std::cout << (int)i << "," << std::endl;
}
期待している結果: 1,2,3,4,5...と連番になる
たまに起こる結果: 1,2,3,5,6...と歯抜けになる
2019/10/04(金) 23:42:33.92ID:8yIxxMU3
丸められただけでは
2019/10/04(金) 23:55:23.10ID:YWySipM2
>>341-344
また5ch名物のしょーもない煽り煽られの流れかとおもったら
ちゃんと勉強になる流れでワロタ
2019/10/05(土) 00:03:15.79ID:bnoeYdBm
行列の結合則なんて高校で習っただろ
線形代数わからないプログラマって生き残れないと思うわ
2019/10/05(土) 00:05:26.41ID:KADe2ROY
>>347
・そのコードは、完全に上記の通りですか?

例えば、ループ回数が1000回より遥かに多くなると、
誤差の都合でそうなることがあるかもしれませんが、1000回くらい
だと、正しい処理系ではその現象は起きないはずです。
2019/10/05(土) 01:17:38.13ID:d5aP5JOP
キャストする前にlround呼んだらええんちゃうん。
2019/10/05(土) 01:44:04.24ID:VkhEKreX
(0.2+0.3)+0.4 == 0.2+(0.3+0.4)の結果がfalseになるのは正しいの?
2019/10/05(土) 01:54:00.97ID:Lbi5NeET
浮動小数点を勉強しておいで
2019/10/05(土) 02:07:17.64ID:5hJZ4CgN
有効数字1桁の計算で誤差は生じない
2019/10/05(土) 07:04:22.03ID:UfPJq4d2
10進の0.1を2進表現すると循環小数定期

>>355
バカ乙
2019/10/05(土) 08:03:13.32ID:9T2eUTn8
>>336
本当、人って色々だな
俺はC++98は未完成感があまりに強くて続きはまだかと待ちかねていた
具体的には例えば右辺値参照だ
一時オブジェクトにいちいちconstがつくのがイヤでイヤで待望のやつがやっと来た
2019/10/05(土) 08:28:45.86ID:iS4eZEWC
>>337, >>340
ちょっと誤解招くのでやっぱ突っ込んでおくけど、
多数のベクトルを変換するのに行列をまとめておかないと無駄になるのはどっちの方式でも同じだよ
俺が言ったのは(少なくとも同一の行列が)一度限りしか出てこない場合の話
まぁそれを最適化する必要があるのか、またそういう処理を大量にループするなら最適化の方法は他にあるだろうけど
>>333
GL方式でも列優先だから結局d3dと同じ無駄はあるんやで
最近のは知らんけど
2019/10/05(土) 08:49:33.11ID:KADe2ROY
>>353
計算誤差です。
(0.2+0.3)+0.4 == 0.2+(0.3+0.4) が偽になっても
(0.2+0.3)+0.4 == (0.2+0.3)+0.4 や
0.2+(0.3+0.4) == 0.2+(0.3+0.4)
は必ず真になることが保障されています。
2019/10/05(土) 08:55:38.66ID:KADe2ROY
>>359
コンピュータにおける浮動小数点は、内部表現は10進数ではなく2進数
で表現されており、有効桁数は 10 進数で 8 桁や 15桁などではなく
2進数で xx BIT という風になっています。
0.2, 0.3, 0.4 は、10進数だと、有効桁数が1桁でも完全に区切れが
よく表現できていますが、2進数の表現だと厳密には無限小数になってしまい、
どんなに有効桁数を長くしても厳密には表現できません。そのため計算誤差
が生じるのです。0.5 や 0.25 や 0.125 は 2 進数でも区切れ良く表現できるため、
 (0.125+0.25)+0.5 == 0.125+(0.25+0.5)
は誤差が生じることがないため、必ず真になるはずです。
2019/10/05(土) 10:06:32.18ID:e1uvrqu3
>>360
浮動小数の計算誤差を考慮して比較する時にstd::abs(a-b) < std::numeric_limit<double>::epsilon()というふうにするのはどう思う?
2019/10/05(土) 11:34:20.93ID:KADe2ROY
>>361
誤差の量が計算の順序や書き方によって変わってくるので、
そのようなヘッダに書かれているような誤差定数を使うことは
余り意味がありません。
2019/10/05(土) 11:37:49.72ID:7pdQvekm
実用数学
2019/10/05(土) 11:43:08.23ID:rY1OpV0v
>>361
機械イプシロンはそういうふうに使うものじゃない
2019/10/05(土) 12:09:22.39ID:uol03Q2n
cpprefjpが>>361と全く同じ間違いしてたわ馬鹿が湧くのはこいつのせいか
cppreference.comは正しかったからそっち見れ
2019/10/05(土) 12:34:57.85ID:dFaPF8AB
>>365
x-yの元になっているxやyがどのような計算過程を経てきたかわからないのに
 std::abs(x-y) <= std::numeric_limits<T>::epsilon() * std::abs(x+y) * ulp
でxとyがalmost equalsと言い切ってよい根拠とは、

ちゅか常識的に考えて、x、yがそれぞれ±e、±gの誤差を有するなら
 std::abs(x-y) <= std::numeric_limits<T>::epsilon() * (std::abs(e) + std::abs(g))
あたりの判定に落ち着かねばおかしい(これで正解とは言っていない

なんでstd::abs(x+y)みたいな場合によっては莫大な値になりえる係数を掛けねばならないの?
2019/10/05(土) 13:04:02.75ID:rY1OpV0v
イプシロンに誤差を掛けても意味ない。
つか、許容誤差の絶対値が与えられているならイプシロン使う必要もない。
cppreference.comのは許容誤差をULP単位で与える場合のやりかたで、
abs(x+y)はxとyの指数のうち大きい方を意味するものだったはず。
2019/10/05(土) 13:12:59.71ID:uol03Q2n
>>366
なんか色々根本的に勘違いしてる
cppreference.comのalmost_equal関数の仕事はあくまで与えられたxとyがalmost equalかどうかの判定だよ
> x、yがそれぞれ±e、±gの誤差を有するなら
なにこれ?「誤差」って何に対する何の誤差?
2019/10/05(土) 13:28:00.03ID:dFaPF8AB
>>367
>イプシロンに誤差を掛けても意味ない。
>つか、許容誤差の絶対値が与えられているならイプシロン使う必要もない。
左様ですなスマンカッタorz

>>368
>なにこれ?「誤差」って何に対する何の誤差?
真の値に対する誤差じゃわパオーン
真の値に対する誤差に依存しないalmost equal判定とか、使いどころはきわめて限定されるはず、
2019/10/05(土) 14:05:34.77ID:dFaPF8AB
>abs(x+y)はxとyの指数のうち大きい方を意味するものだったはず。
xが (xの符号)×1.bbbb...×2^m
yが (yの符号)×1.cccc...×2^n
だとしたときに、m>nだとすると
 x + y =
 { (xの符号)×1.bbbb... + ((yの符号)×1.cccc...×2^-(m-n)) } ×2^m
として計算されるのでだいたい2^m(x≒yなら2^(m+1))という意味か左様か、
2019/10/05(土) 14:08:05.45ID:dFaPF8AB
んまーulpをxとyの来歴に応じて調整すべき量とするなら
cppreference.comのalmost_equal関数は理解してやらないでもない
2019/10/05(土) 16:03:17.50ID:NXndjuW4
だれか、俺に分数を教えてくれないか?
足し算と引き算がマジ解らなくなってるんだ。
https://ideone.com/IfCcGz

一番のネックはネガフラグの扱い。
マイナスとプラスの反転演算でどうかくとスマートだろうか。
だれか教えてプリーズ。
2019/10/05(土) 16:21:25.21ID:bnoeYdBm
分子に符号もたせりゃいいだろ
2019/10/05(土) 16:25:36.94ID:NXndjuW4
>>373
え、それでよかったっけ?
2019/10/05(土) 16:34:31.54ID:hwiNAqBO
>>350
今習わないよ
俺の時でも選択
2019/10/05(土) 17:18:56.47ID:NXndjuW4
一応以下のような感じになった。Thx!
http://coliru.stacked-crooked.com/
2019/10/05(土) 17:19:54.63ID:NXndjuW4
http://coliru.stacked-crooked.com/a/5fa6ab838f9ff15a
こっちだった。Orz

んじゃ。
378デフォルトの名無しさん
垢版 |
2019/10/05(土) 17:28:26.58ID:QHD8CUaF
>>377
1. constexprにしてもいいんじゃない?
2. 出力関数作成しよう

template<typename Char>
std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os, const Fraction& frac){
return os << frac.GetNumerator() <<'/'<<frac.GetDenominator();
}
2019/10/05(土) 19:08:43.36ID:NXndjuW4
>>378
1.できなくはない。機械的に接頭語つけるだけでいいよね。
2.暇だから作るわ。

行ってきまーす。
2019/10/05(土) 19:46:54.47ID:NXndjuW4
https://ideone.com/uzd7EF
ただいまー。イデオンで動かせるようにした。Gcdがバグってないといいなぁ。
あとvc2019では意味不明なエラーで動かない。
2019/10/05(土) 19:58:28.51ID:NXndjuW4
フィードバックハブに投げておいた。
382デフォルトの名無しさん
垢版 |
2019/10/06(日) 10:28:58.03ID:yc9LKsYB
>>380
マルチ禁止
2019/10/06(日) 13:42:53.69ID:bPt7YQEe
>>382
ソーリー。
2019/10/07(月) 19:17:43.20ID:PHxdOQnu
C++ってなんでヘッダファイルいるんですか
最近マシン早いんだし
全部ソースに書いてインポートすればいいのに
2019/10/07(月) 19:38:58.27ID:Xs+XlBV4
やれば?(クレヨンしんちゃん風に)
2019/10/07(月) 19:52:54.51ID:9pxPpXZa
来年まで待ってね
2019/10/07(月) 20:58:42.59ID:A3KSW75p
>>384
むしろソースがいらなくて全部ヘッダに書けばいい
inline変数とかもできるようになったことだし
2019/10/07(月) 21:05:07.29ID:8FnUNDHt
>>387
たまに趣味で何でもかんでもtemplateでゴリゴリ実装してるとガチでそれになるww
2019/10/07(月) 21:26:10.24ID:YMM6HSZT
>>385
ヤレばデキるは魔法の言葉
2019/10/08(火) 09:06:39.07ID:xr4jQIWZ
プリコンパイルヘッダーって使ってます?

使っているプロジェクト見たことないですわ。
2019/10/08(火) 20:03:58.69ID:kGAGzuS0
>>387
こういう馬鹿野郎が出てくるからメタプロとかテンプレ好き連中ってのは嫌いなんだよ。
2019/10/08(火) 21:04:41.31ID:OCfPMe68
C++なんて趣味でやってるんだからテンプレ好きでもええやん
2019/10/08(火) 21:16:41.69ID:/kdim2Vo
出てくることの何が嫌なんだろうか
はっきり言って病気だ
2019/10/08(火) 21:42:59.95ID:lGNioH0G
headerオンリーってのは可搬性に優れた良いものだろ
特にテンプレート多用している奴は、一部関数だけソースファイル分離する意味が薄い
2019/10/08(火) 21:43:38.32ID:asJ1ctJB
>>391
どんなものにだって馬鹿は出てくるだろうに
2019/10/08(火) 21:54:07.26ID:J87hrB1p
「全部ヘッダ」と言われると、そのときの「ヘッダ」の定義がどういうものなのか気になる。
2019/10/08(火) 21:57:19.52ID:EwyBASw5
趣味でやってる人は全部ヘッダでいいと思う
2019/10/08(火) 22:09:52.63ID:tSj7di+z
>>390
VCのやつは使いまくり
依存するライブラリのヘッダファイルを標準のやつもソリューション内のやつも全部まとめて
stdafx.hの中でインクルードしたらことのほか便利
ただし同じプロジェクトのヘッダファイルを入れだしたら目的を見失って氏ぬ
2019/10/08(火) 22:10:50.35ID:hpLG4xMo
テンプレート関数は便利だしconstexpr関数は市民の義務だし
結局ほとんどヘッダファイルに書くことになるでしょ
2019/10/08(火) 22:30:34.35ID:X4FGjRpd
初心者ですが質問させてください

print(1, 3.14, "abc");とやると引数の中身を順番にスペース区切りで出力してくれるような関数は
可変引数テンプレートの再帰呼出しを使うと便利にできることを知りました。
そこで引数の型に応じて出力の見た目を少し変えたいのですが、
関数の特殊化をすればいいですか?
typeidだと動的な評価になってしまうんですよね?
2019/10/08(火) 22:33:59.15ID:kGAGzuS0
予想通りの馬鹿回答で笑ってしまった。
やっぱいい判別になるわテンプレバカ。
2019/10/08(火) 22:37:33.87ID:jfG+k1ni
>>400
引数一つに対するテンプレート関数を作って特殊化してそれに少しずつ渡せばできるよ。
2019/10/08(火) 22:42:38.66ID:/kdim2Vo
C++嫌いなのにいつまで居座るんだろうなこのガイジ
2019/10/08(火) 22:57:34.25ID:HxNAD6ah
好き嫌いの問題じゃねーんだわ
2019/10/08(火) 23:04:05.43ID:/kdim2Vo
こんな雑談スレ好きな奴以外に需要ないだろ
こんな辺境別に見なくて良いんだよ?
2019/10/08(火) 23:08:13.69ID:hpLG4xMo
>>400
c++17以降ならif constexprとstd::is_same_vの使用を検討してみるのもいいかも
2019/10/09(水) 04:08:22.18ID:NmoqHfbB
400です。頑張ってみましたがどうにもコンパイルエラーが出ます
難しいですねC++は...

void print() {}

template<class... Args>
void print(const char* c, Args... args) {
cout << "[" << c << "]" << endl;
print(args...);
}

template<class First, class... Args>
void print(First first, Args... args) {
cout << first << endl;
print(args...);
}

int main() {
print(1, 3.14, "abc");
return 0;
}
2019/10/09(水) 04:17:51.46ID:NmoqHfbB
あ、こういうふうにするとコンパイルできました。引数2個の関数を特殊化したからエラーになった?
テンプレートの展開のされ方がよくわからないけど、とりあえず目的のことはできました
ありがとうございました

void print(const char* c) {
cout << "[" << c << "]" << endl;
}

template<class T>
void print(T t) {
cout << t << endl;
}

template<class First, class... Args>
void print(First first, Args... args) {
print(first);
print(args...);
}
2019/10/09(水) 04:21:52.30ID:NmoqHfbB
>>406
いわゆる型特性というやつでしょうか?enable_ifを使うのかと思い試したもののうまくいかず、
ネットで調べるとenable_ifと可変引数テンプレートは相性が悪いという意見を見つけたり...
2019/10/09(水) 07:02:07.47ID:8qv563yz
>>409
if constexprを使った例はこんな感じ
template<class First, class... Args>
void print(First first, Args... args) {
if constexpr(std::is_same_v<First, const char*>){
std::cout << "[" << first << "]" << std::endl;
} else {
std::cout << first << std::endl;
}
if constexpr(sizeof...(args)>0){
print(args...);
}
}
411デフォルトの名無しさん
垢版 |
2019/10/09(水) 10:59:59.89ID:RbUf+g7C
const char * 自体も class First や class Args と一致するんじゃね
2019/10/09(水) 21:59:58.44ID:8qv563yz
First と Argsの二つがあるのがややこしい場合は畳み込み式でもできるぞ

template<class... Args>
void print(Args... args){
  ([](auto t){
    if constexpr(std::is_same_v<decltype(t), const char*>){
      std::cout << "[" << t << "]" << std::endl;
    } else {
      std::cout << t << std::endl;
    }
  }(args), ...);
}
2019/10/09(水) 22:42:32.58ID:J+0BhmRu
win系のOSの画面に1.txt~5.txtがあります。1.txtと2.txtをドラッグして選択したとします。
この状態で3.txt~5.txtを選択したことにするにはどのようなコードを書けば良いですか?
2019/10/09(水) 22:52:59.82ID:bPxMjWa1
>>413
ListView_SetItemState
2019/10/10(木) 00:29:05.87ID:uUO69neG
エクスプローラにdll注入とか?
2019/10/10(木) 01:32:41.34ID:VnnXeZwz
前にやったことがある。
https://github.com/katahiromz/SysNotifyHooker
2019/10/11(金) 01:40:25.90ID:n351RXRL
std::shared_ptrを構築後に(カスタム)デリータを変更するのは無理?

既にどっかで作成済みのshared_ptrについて、破棄タイミングを後から見れないかなと
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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