質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

433閲覧

エラーが出ずにコンパイル終了しないコードについて

jbe00214

総合スコア63

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2023/02/05 03:19

実現したいこと

 次のコードは実行時に再帰するコードですが,なぜか,エラーは何も表示しないのに,コンパイルが終わりません。mac と ubuntu の両方で同じ現象です。
基本的なミスがあるとしても,文法上のエラーは出ないのは不思議です。
どこが問題なのか,どなたか教えていただけませんか。

該当のソースコード

C++

1#include <tuple> 2template<typename Tuple,typename Func> 3auto nRunMakeTupleLoop(std::size_t N,std::size_t D, Tuple&& tuple,Func func){ 4 auto ob = func(); 5 auto t = std::tuple_cat(std::forward<Tuple>(tuple), std::make_tuple(ob)); 6 if ( N == D ) 7 return t; 8 else 9 return nRunMakeTupleLoop(N, D+1,std::forward<decltype(t)>(t), func); 10} 11 12template<typename Func> 13auto nRunMakeTuple(std::size_t N,Func func){ 14 auto ob = func(); 15 auto tu = std::make_tuple(ob); 16 if ( N == 1 ) 17 return tu; 18 else 19 return nRunMakeTupleLoop(N,2, std::forward<decltype(tu)>(tu),func); 20} 21 22struct C{}; 23 24int main(int argc, char**argv){ 25 26 auto obs = nRunMakeTuple(3,[](){ 27 return new C; 28 }); 29 30 delete std::get<0>(obs); 31 delete std::get<1>(obs); 32 delete std::get<2>(obs); 33}

補足情報(FW/ツールのバージョンなど)

mac 13.2 clang
c++20 でコンパイル

ubuntu 22.04
gcc 11.3.0

コンパイルオプション -std=c++20

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

N==D は実行時の停止条件です。 コンパイル時は if の条件に関係なく両側にあるテンプレートを展開しようと試みます。

結果として型引数 Tuple の部分が異なった nRunMakeTupleLoop を際限なく実体化しようとして無限ループに陥ります。

投稿2023/02/05 04:29

SaitoAtsushi

総合スコア5444

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbe00214

2023/02/05 05:12

いつもありがとうございます。コンパイル時無限ループということがあるとは思いませんでした。ありがとうございました。
SaitoAtsushi

2023/02/05 08:49

コンパイラの都合によってテンプレートの実体化の再帰に上限を設定してもよく、仕様としての要求というわけではないという断り付きで 1024 をガイドラインとすると規格には書かれています。 https://timsong-cpp.github.io/cppwp/n3337/implimits#2.37 停止条件が付いていないテンプレートが単純なものであればこの上限にすぐに達してエラーになるのですが、この数値はテンプレートのネストの「深さ」に関する制限なので幅方向の広さもある構造になっている場合にはなかなかエラーにならずに時間やメモリを消費し続けてしまうということも起こりえます。 たとえばこういう間違いをしても一瞬でエラーとして帰ってくるのですが…… template <int n> void foo(void) { if(n!=0) { foo<n-1>(); } } int main(void) { foo<10>(); } おそらく std::tuple_cat もそれなりに複雑なテンプレートでしょうし、上手い (?) 具合に厄介なパターンを引き当ててしまったのでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問