C++相談室 part158

■ このスレッドは過去ログ倉庫に格納されています
2021/11/15(月) 18:49:18.44ID:I69rZ/Of
前スレ
C++相談室 part157
https://mevius.5ch.net/test/read.cgi/tech/1628474251/
2022/01/20(木) 18:29:19.36ID:PFfSIkf2
ぐぶー・・・
2022/01/20(木) 22:37:24.73ID:Df2OyNH0
ランタイムサポートが必要なC++言語機能ってRTTIやdynamic_cast、例外くらい?
2022/01/20(木) 23:29:32.85ID:a5eQ4sV9
そもそもランタイムサポートの定義をちゃんとしないとな・・・
2022/01/21(金) 00:00:01.47ID:/d5tBos9
RTTIも例外も標準C++の一部
それが使えないような設定は厳密には規格違反だし、それで高速化や効率化しますってのは各コンパイラの独自機能に過ぎない
2022/01/21(金) 01:04:31.52ID:VVQk5y8F
アホすぎるw
2022/01/21(金) 07:18:18.80ID:j/G12RQ8
dynamic initializationも裏で色々やってるね
2022/01/21(金) 07:28:47.34ID:VVQk5y8F
とりあえずOSないところか、簡単な仕組みしかないところでC++で何か書いてみればいいよ
処理系が何をしてくれているのか分かる
2022/01/21(金) 07:43:11.40ID:j/G12RQ8
ベアメタルはオモロイ
2022/01/21(金) 07:59:33.55ID:j/G12RQ8
658だけど、自己解決の報告。
テンプレートにしないで
void test(int(*f)(int)){}
にしたら<locale>のisprintが干渉しなくなった
最初の発想がいかんかった
2022/01/21(金) 08:26:30.46ID:VVQk5y8F
isprintのテンプレート引数が決まらないからだろ
test(std::isprint<int>);
とかなら通ると思う
2022/01/21(金) 08:32:03.82ID:VVQk5y8F
compiler explorerのarm g++ 10.3で確認した。ヘッダはlocaleにした。
#include <locale>
template <typename F>
void test(F&& f){}
int main(){
//test(std::isprint);
test(std::isprint<int>);
}
2022/01/21(金) 08:47:07.93ID:VVQk5y8F
元のコードをなるべく変えずにだと
#include <string>
#include <cctype>
template <typename F>
void test(F&& f){}
int main(){
test(static_cast<int (*)(int)>(std::isprint));
}
※オーバーロードを選択させるべくキャストする
2022/01/21(金) 09:54:53.25ID:j/G12RQ8
conceptでテンプレートテンプレート引数を弾いたりできないかとも思ったけど
SFINAEは関数の除外なので引数の候補を絞るのは無理だった
2022/01/22(土) 10:28:58.52ID:om6KWGu4
class A { static inline struct SubStruct { int value; } Field1; } //通常の構造体のスタティックメンバ変数はヘッダファイル、cppファイル共に実体は同じ
class A { static inline struct { int value; } Field1; } //無名構造体のスタティックメンバ変数はヘッダファイルとcppファイルとでそれぞれ別の実体が生成されアドレスが異なる

この挙動は仕様なのでしょうか?
2022/01/22(土) 10:57:07.60ID:OQdcFc3P
名前書き忘れて0点取ったことないのか
2022/01/22(土) 11:38:04.16ID:+VFNw8nk
今だと仮想関数とvariantとどっち使うのが主流ですか?
2022/01/22(土) 11:49:22.43ID:XNgWTOyh
>>675
名前のない構造体には実体がなく外部リンケージを持たないのでそこに対するinline指定は無視されるってことでは?
分かりにくいけど仕様として矛盾してはいないと思う
2022/01/22(土) 13:06:33.51ID:BllOBQpy
>>675
「ヘッダファイルとcppファイルとでそれぞれ別の実体が生成されアドレスが異なる」という状態をどうやって観測しているの?
そんな挙動しないと思うんで、観測方法に間違いがありそう。

>>678
名前のない構造体もクラス型としては存在するし、それとは別に変数 A::Field1 は外部リンケージを持つよ。
https://timsong-cpp.github.io/cppwp/n4861/basic.link#5
> In addition, a member function, static data member, ..., has the same linkage, if any, as the name of the class of which it is a member.
2022/01/22(土) 13:08:52.36ID:BllOBQpy
>>678
あと仮にinline指定が無視されたとしても「別の実体が生成される」というような動作には繋がらないね。
2022/01/22(土) 13:59:06.18ID:0LC8SyT+
>>599
アーハン?
doubleで表現可能な最小の数と1e-14の大小関係もわかんない人なんですかね、、、
2022/01/22(土) 14:05:40.45ID:0LC8SyT+
>>593
その2π周期というのが厳密に2*M_PI周期であることの根拠は?
>>560の時点ではそれは示されていなかった
>>588で2*M_PI周期と言う実験結果がデタ
2022/01/22(土) 14:11:22.71ID:0LC8SyT+
>>596
万能の一般論は無い(キリ
なぜなら、f(x)が0かどうかの判定をしたいとして、±|處を0とみなすべきなのかは
f(x)の精度に依存するから
ただし、>>560式に f(x1) と f(x2) の等値判定なら >>560式にやりうる
これは f(x1) - f(x2) のゼロ判定として>>560式にやればよろっし
2022/01/22(土) 14:15:01.32ID:0LC8SyT+
アンカーミスった;;;orz
s/>>560/>>588/g
2022/01/22(土) 16:12:55.51ID:13b+4FON
>>681
O(1) の数値を使って計算してたら例えば 1e-15 以下の数値をゼロと見なすとかするより他ないでしょ
バカ?
2022/01/22(土) 16:30:03.25ID:OQdcFc3P
sedかよ
2022/01/22(土) 16:59:40.11ID:gWLf+Bka
知らなくて驚くかもしれないけどdoubleは1e-324も表せちまうんだ
2022/01/22(土) 17:34:26.32ID:UJcbhjLZ
>>681-687
まだやってたのか小学生・・・ID変えてご苦労様
何度も言ってるが>>560でこの話は終了している
2022/01/22(土) 17:48:02.61ID:vZsc1PCZ
>>687
そこまで拗らせてる事に驚いたわw
2022/01/22(土) 19:34:50.12ID:DSkywrpw
>>560
>100万をsin()しても、sin()は2π周期
>doubleの精度15桁中の5桁以上を無駄にしている

これよくわからん。
2022/01/22(土) 20:03:51.19ID:0LC8SyT+
言ってる当人もわかってないんだろJK
2022/01/22(土) 20:37:14.45ID:0LC8SyT+
double sin(double x)の精度が±10E-10程度らしいことは>>588の結果が示しているが
こっれはxが100万かどうかによらないことも結果が示してゐる
実装を見ないとわからんが、多分マクローリン展開の打ち切りによる誤差とみるべき
2022/01/22(土) 21:05:23.18ID:yfbq4hUz
>>692
実装見てから言った方がいいよ。マクローリン展開というが、0を基準にマクローリン展開してるわけないだろ。
2022/01/22(土) 21:18:55.93ID:0LC8SyT+
>>685
その方法は等値判定として一貫性が無いからNG
double x = 2.0;
double y = 2.0 + (10E-15) / 2.0;
assert(fabs(x - y) <= 10E-15); // pass. 10E-15基準で x == y とみなされる
assert(fabs(100 * x - 100.0 * y) <= 10E-15); // fail。 10E-15基準の下で 100 * x と 100.0 * y はイコールにならにあ
2022/01/22(土) 21:22:04.30ID:0LC8SyT+
>>693
sin(x)の場合は|x|<<1においてsin(x) ≒ xなのでsin(x+a)を展開をする際のaを0にするのが妥当に思えまっする、
2022/01/23(日) 04:16:28.14ID:QgynSmAQ
>>689-695
まだやってたのか小学生・・・ID変えてご苦労様
何度も言ってるが>>560でこの話は終了している
2022/01/23(日) 09:39:04.54ID:CWW/bMN0
>>678
挙動としては正にそんな感じですね

>>679
test.hにあるinline void 内でprintf("%p\n", Field1)、test.cppのvoid Func1内で同様の事をして確認しました
出力のみならず、そもそもヘッダのinline void内でField1に値をセットしたはずなのにソース内ではデフォルト値のままで動作が狂ったので上記のテストをして発覚した次第です
structを名前付きにするかしないかの一点だけで上記の結果が変わります
2022/01/23(日) 09:40:35.92ID:CWW/bMN0
>>697
printf("%p\n", Field1)はレス間違いでprintf("%p\n", &Field1)で実験しています
2022/01/23(日) 10:41:30.96ID:QgynSmAQ
#include<iostream>
struct A{static struct SubStruct{int value;} Field1;};
A::SubStruct A::Field1;
int main() {
std::cout << std::hex << &A::Field1 << std::endl;
return 0;
}
無名で実体の定義なんてできんのか?
2022/01/23(日) 10:43:19.72ID:vZkrAotW
キャストやconst&でできるな
2022/01/23(日) 10:47:03.39ID:QgynSmAQ
>>700
どうやんの?上の例でやってみてよ
2022/01/23(日) 10:48:14.26ID:QgynSmAQ
ちなみに上の例は無名でない構造体で、実体の定義は
A::SubStruct A::Field1;
2022/01/23(日) 10:51:00.92ID:CWW/bMN0
>>699
C++20だか17だかからはinlineをつける事で出来ます
2022/01/23(日) 10:51:47.13ID:QgynSmAQ
#include<iostream>
struct A{static struct {int value;} Field1;};
decltype(A::Field1) A::Field1;
int main() {
std::cout << std::hex << &A::Field1 << std::endl;
return 0;
}
意外とやってみたら出来たw
2022/01/23(日) 10:55:02.08ID:vZkrAotW
>>700

A::SubStruct{}
で実体の「定義」ができる

&A::SubStruct{}
は実体がprvalueという理由でエラーだが
実体を定義できるか否かとは別問題だ
2022/01/23(日) 10:57:42.35ID:QgynSmAQ
>>705
根本的に意思疎通できてないみたいだな
staticメンバA::Field1の実体定義だって
2022/01/23(日) 10:59:48.93ID:vZkrAotW
>>706
そのようだな
なぜstaticメンバが出てくるのか不明だ
2022/01/23(日) 11:04:13.16ID:QgynSmAQ
>>703
確かに出来た
-std=c++17
付けたら実体定義なくても通った
2022/01/23(日) 11:05:12.08ID:QgynSmAQ
コードはこんなのね(with -std=c++17)
#include<iostream>
struct A{static inline struct {int value;} Field1;};
int main() {
std::cout << std::hex << &A::Field1 << std::endl;
return 0;
}
2022/01/23(日) 11:25:38.49ID:QgynSmAQ
実体は同じのを指すようで再現しなかったな。MakefileはちゃんとTAB入れてな。
cat >Makefile <<EOF
CXXFLAGS += -std=c++17
sample: main.o sub1.o sub2.o
\$(LINK.cc) \$? -o \$@
EOF
cat >main.cpp <<EOF
void sub1();
void sub2();
int main() {
sub1();
sub2();
return 0;
}
EOF
cat >sub1.cpp <<EOF
#include<iostream>
struct A{static inline struct {int value;} Field1;};
void sub1() {
std::cout << std::hex << &A::Field1 << std::endl;
}
EOF
cat >sub2.cpp <<EOF
#include<iostream>
struct A{static inline struct {int value;} Field1;};
void sub2() {
std::cout << std::hex << &A::Field1 << std::endl;
}
EOF
make
2022/01/23(日) 15:40:28.67ID:K/S7vg9Z
>>697-698
wandbox の gcc 11.1.0 でもやってみたけど、再現せず同じアドレスが出た。
https://wandbox.org/permlink/SSg6OZD97wmgR8kq
コンパイラやバージョンやコンパイルオプションを合わせれば再現するのかね?
2022/01/23(日) 15:53:41.49ID:QgynSmAQ
>>711
複数のオブジェクトファイルにしないと検証できないと思うよ
2022/01/23(日) 16:09:46.74ID:K/S7vg9Z
>>712
>>697の説明にあるtest.cppはtest.hをインクルードしてるんだろうからこの形でいいだろうと思った。

まぁやってみたけど、変わらないね。
https://wandbox.org/permlink/hfbakWmCF1i5stqr
2022/01/23(日) 16:31:20.27ID:QgynSmAQ
>>713
流石にヘッダファイルから何かが生成されることはないw
wandboxで複数オブジェクトファイルって処理系内部の作り次第になるし、>>710でもやってみようかと思ったけど、3つは無理そうだね
2022/01/23(日) 17:20:50.76ID:hHkcGLX7
ヘッダに実装書くと管理が楽だよね
2022/01/23(日) 17:32:20.44ID:CWW/bMN0
>>711
検証頂いてるところ環境を明記しておらず申し訳ありません
Visual Studio 2022、C++20で発生している現象です

#include "test.h"
int main() //main.cpp
{
A::Initialize(); //printf("%p\n", &A::Field1);をするだけのstatic inline関数
A::Func1(); //printf("%p\n", &A::Field1);をするだけのstatic関数(__declspec(noinline)をし実装はtest.cpp)
}

struct名をつければInitializeの出力とFunc1の出力は一致、無名structにしたら不一致
本当に他は一切いじらずに名前の有無だけで変わります
2022/01/23(日) 17:54:11.09ID:QgynSmAQ
現象を再現させる最小限のコードを全セット載せないと先には進まんて
始めからそうしてればこんなにいろいろ書かずに済んでいる
2022/01/23(日) 18:17:03.90ID:K/S7vg9Z
>>714 wandbox でも -v 追加で as が2つ test.cpp と prog.cc と別で走ってるのまでは見た。
2022/01/23(日) 18:18:38.46ID:K/S7vg9Z
>>716
MSVC のバグっぽいね。おとなしく名前つけて回避しつつ、できればバグ報告しとくのがいいんじゃない。
2022/01/23(日) 20:02:54.49ID:QgynSmAQ
>>715
>>675で「無名構造体のスタティックメンバ変数はヘッダファイルとcppファイルとでそれぞれ別の実体が生成されアドレスが異なる」
と書いてあるが、ヘッダファイルから直接実体は生成されないよってこと
.cppなどのソースファイルからincludeされないとコンパイルしないから
(もちろんただのファイル名なのでコンパイラに直接ヘッダファイルをコンパイルせよと指定する事はできる)

つまりA::Field1に該当するシンボルが複数の.objに含まれた場合、同じになっているか=アドレスが同じになるか?
の検証でないと意味がない
2022/01/23(日) 20:09:37.28ID:QgynSmAQ
>>718
それは昔からgccを使ってる人は知ってるけど、そういう話じゃない
明らかに不自然な位置にソースファイルを指定して無理矢理2個同時にコンパイルする上に、引用されて3個はできない
つまり想定された使い方ではないということ
おまけに処理系やそのバージョンを複数変えられることが比較的便利なwandboxで、処理系を変えると確認が必要になるやり方はどうかと言っただけ
まあ、分かってるとは思うんだが
2022/01/23(日) 20:24:03.88ID:QgynSmAQ
とりあえず、710のコードでVS2019を調べた結果、再現は確認できた。
ただし、コンパイルオプション次第で現象が出たり出なかったりする。
VS2022でもないし、VSはコンパイルリンクオプションがデフォルトで大量に指定されてて確認が面倒なのでそれ以上は放棄した。
以下のコードではpermissive-オプションの有無で現象が再現したりしなかったりするが、デフォルト時だとその切替えで現象は変わらないので、一次原因ではないと思う。
2022/01/23(日) 20:24:36.31ID:hHkcGLX7
保守できないような書き方して自分の仕事を守る。PGの当然の権利ですよね。
2022/01/23(日) 20:25:06.27ID:QgynSmAQ
> main.cpp (
@echo void sub1^(^);
@echo void sub2^(^);
@echo int main^(^) {
@echo sub1^(^);
@echo sub2^(^);
@echo return 0;
@echo }
)
> sub1.cpp (
@echo #include^<iostream^>
@echo struct A { static inline struct { int value; } Field1; };
@echo void sub1^(^) {
@echo std::cout ^<^< std::hex ^<^< ^&A::Field1 ^<^< std::endl;
@echo }
)
> sub2.cpp (
@echo #include^<iostream^>
@echo struct A { static inline struct { int value; } Field1; };
@echo void sub2^(^) {
@echo std::cout ^<^< std::hex ^<^< ^&A::Field1 ^<^< std::endl;
@echo }
)
> sample.mak (
@echo CXXFLAGS = /MDd /EHsc /std:c^+^+17 /permissive-
@echo .cpp.obj:
@echo $^(CXX^) $^(CXXFLAGS^) /c $^<
@echo sample.exe: main.obj sub1.obj sub2.obj
@echo link /OUT:$@ $^*^*
)
nmake /f sample.mak
rem バッチファイルもnmakeもよく知りません。
2022/01/23(日) 20:34:19.55ID:K/S7vg9Z
>>721 ソース3つ以上もできるよ。 https://wandbox.org/permlink/UgIc9mFrs59059jq
2022/01/23(日) 20:40:05.18ID:QgynSmAQ
>>723
そういうのはプロジェクトの方針だと思うので、ここで話す内容ではないと思うよ
2022/01/23(日) 20:45:20.80ID:QgynSmAQ
>>725
改行と空白で違うのかよw b烽、知るかってャ激xルだけど、bりがと
bニりあえず>>710を載っけとく
https://wandbox.org/permlink/e8khwggKe00rtekJ
2022/01/23(日) 20:49:22.51ID:QgynSmAQ
>>723
>>727は何故だか文字が化けてたので一応書き直しとく。

改行と空白で違うのかよw もう知るかってレベルだけど、ありがと
とりあえず>>710を載っけとく
https://wandbox.org/permlink/e8khwggKe00rtekJ
729デフォルトの名無しさん
垢版 |
2022/01/24(月) 19:27:55.24ID:WxnVLAIm
C++11から、C++20までの変更点を解説した入門書を年末に買ったのだが(C++は書けるよ)、まだ読む気になれないw
「今更C++か、pythonでいいだろ」と悪魔が囁くw
2022/01/24(月) 19:42:15.63ID:nLfFXIoN
c++cliについてネットに解説している情報あまり無いですが、まとまってるサイトとかないですかね。
2022/01/24(月) 20:29:40.39ID:kghIRcG8
https://docs.microsoft.com/ja-jp/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp?view=msvc-170
2022/01/25(火) 08:07:34.25ID:m+e4/QVD
めずらしい
変態に興味あるとは
VisualJ++とかワケワカだったぜw
2022/01/26(水) 05:15:43.56ID:DGJ/MazB
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()が呼ばれた時に描画だけでなく画面の更新もされるようにするにはどうすればよいですか?
2022/01/26(水) 06:35:00.77ID:R08bxH5q
WM_TIMERでBeginPaintはおかしいぞ
WM_PAINT専用なんだから
無効領域ないのにBeginPaintしたらあかん

[誘導] 続きはこっちでな
Win32API質問箱 Build127
https://mevius.5ch.net/test/read.cgi/tech/1639053176/
2022/01/26(水) 07:17:52.16ID:T9eKedNN
InvalidateRectとかGetDC〜ReleaseDCだっけ?
2022/01/26(水) 07:50:18.18ID:td9ayUMw
アップデートはマイクロソフトがやりたい時にやる
という基本理念を理解していないようだね
737デフォルトの名無しさん
垢版 |
2022/01/26(水) 09:14:18.23ID:m89Xdimf
WM_TIMERでInvalidateRectしておくとWindowsがWM_PAINT呼んでくれるからそこで描画するんだっけ
2022/01/26(水) 09:17:55.57ID:qvNTvCwo
そもそもこれCだろ…
WinMainから書く超基礎的コードをここで聞く頭がもうね
2022/01/26(水) 09:26:13.12ID:WR8doP3S
べつにアイドルループで描画してもいいんだよ
メッセージの処理さえ忘れずにピークしてこなせば
2022/01/26(水) 09:32:54.79ID:g/1zEXcm
>>738
スレチなのは確かだが、いちいち見下して何がしたいんだお前
2022/01/26(水) 09:36:18.65ID:dkXO6/An
どこにでもいるんだよ
自分より下の者をいたぶることで
安心しようとするチンピラ気質なやつは
2022/01/26(水) 10:21:44.17ID:qvNTvCwo
だってココ定期的に湧くじゃん
Windows使っててWin32APIの使い方聞いてくるC++ほとんど知らない自称天才のバカ
同じやつだよきっと
毎回Win32APIに誘導されてるってのにな
2022/01/26(水) 10:46:25.17ID:g/1zEXcm
あー、言われれば確かにそんなの居たっけ・・
でもまぁ同一人物とは限らないんだし誘導して終わりでいんじゃね
たまに見当違いの初心者は入ってくるし(DirectXスレにDirectXランタイムのインスコの仕方聞きにきた猛者が居た
2022/01/26(水) 10:59:27.08ID:vhiSf69I
733 すいません、そっちのスレは知りませんでした
そちらで聞き直します
2022/01/26(水) 11:06:01.05ID:qvNTvCwo
DirectXスレにDirectXランタイムのインスコの仕方聞くのはまだ仕方ない話
ドライバ固有の問題に当たっているなら専門家に聞いた方がいいだろう

自称天才のバカである確率の方が高いと思うし、高確率で単発IDで荒らすバカも同じだろうし、わざわざレスしてくるやつも同じだろうから、バカにはバカと言ってあげた方が親切
2022/01/26(水) 12:02:29.99ID:dkXO6/An
誘導ももう済んでるのに
どうしても喧嘩言葉を使いたくて沸いてくる
三下のそのまた下の家畜はいいのか
747デフォルトの名無しさん
垢版 |
2022/01/26(水) 13:23:53.73ID:m89Xdimf
DirectXランタイムが許されるならWin32 APIだって許してあげなよ
製品名はVisual C++だし、既定の拡張子 .cpp なんだから Win32はC++ではなくCだって言ってもしょうがない
2022/01/26(水) 23:06:08.50ID:UuxYD5f6
いかにも漏れは天才だが
さすがにWinMain()から書くようなバリバリWindowsアプリの質問はしないかなあ、、、
漏れの言ってることがまるで理解できない低レヴェル凡人の反発を招くことはあってもな
2022/01/27(木) 10:59:27.25ID:Z+Vqme3O
天才でも質問することあるんですね
回答者は超天才?
2022/01/27(木) 11:49:44.22ID:avZQ9Wm7
いかにも
私が超天才だが
ってどっかのハンコ貰いにいく人事のCMみたい
2022/01/29(土) 15:04:46.13ID:mo0R2qbj
大学の課題でコンパイルエラーになるので教えてもらいないでしょうか
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エラー
}
752751
垢版 |
2022/01/29(土) 15:50:41.96ID:mo0R2qbj
失礼、自己解決しました。
namespaceをa.hだけ括って、a.cppに入れ忘れましたw
2022/01/31(月) 02:23:38.98ID:iz74n4+D
下の★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

}
2022/01/31(月) 04:05:32.34ID:y6tOo2ii
>>753
そのようには書けない。 C++ では高階多相を許していない。
2022/01/31(月) 04:18:19.49ID:o5RGUewZ
なんでも適当に済ますクセ
高級言語に慣れすぎの弊害
2022/01/31(月) 14:49:02.61ID:y2HjUy1l
>>753
・まず、Sumを多重定義にする必要性は特にないはず
・次に、fooが関数でSumが関数テンプレートの場合、
 関数の実引数として具現しないテンプレートは渡せない

だからfooの代わりにstd::bindを使っても解決しない

・テンプレートテンプレート仮引数を使っても
 クラステンプレートしか渡せず関数テンプレートは不可

こうなるとマクロくらいしか手がない
#define foo(func, ...) func(__VA_ARGS__)
2022/01/31(月) 16:24:09.60ID:4mzN2AL1
戻り値の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;
// | ^
2022/01/31(月) 20:55:29.83ID:ExACmeMg
>>753
auto Sum = [](auto head, auto... rests) { return (head + ... + rests); };
2022/01/31(月) 22:50:37.06ID:67CF9RIT
ラッパークラスを通せば似たようなことはできそう。

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";
}
2022/02/01(火) 04:38:50.89ID:X9o0BiPI
クラスは不要だった。
ラムダなら通るみたいだから、 >>758 みたいに元の関数をラムダで書くか、

auto wrapper = [](auto... args) { return Sum(args...); };

みたいなラッパー関数オブジェクト通すかってあたりで足りそう。

// 最初実験してたとき、ラムダ式にしただけだとエラー出てた気がしたんだけど、今やると問題なく通る…
2022/02/01(火) 05:38:09.33ID:wGiSz27Y
おお、auto... なんてできたのか
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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