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

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

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

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

Q&A

2回答

1228閲覧

テンプレートクラスと不完全型について

alphya

総合スコア124

C++

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

0グッド

0クリップ

投稿2020/02/13 08:55

編集2020/02/13 10:39

通常、クラスを定義する際、メンバに自分自身を持たせようとすると不完全型なのでエラーになると思います。これは、テンプレートクラスの場合でも同様です。

cpp

1// テンプレートではない場合 2struct X { 3 X x = {}; // X は不完全型なのでエラー 4}; 5 6// テンプレートの場合 7template <typename T> 8struct X { 9 X x = {}; // 不完全型なのでエラー 10};

ここで、メンバに自分自身を持たせようとする際に static inline をつけたとき、テンプレートの場合にはエラーにならないようです。コンパイルは、gcc と clang 両方で試しました。[追記] このとき、実際にインスタンス化して確認しました。また、MSVC で試したところ、Internal compiler error になるようです。

cpp

1// テンプレートではない場合 2struct X { 3 static inline X x = {}; // 不完全型なのでエラー 4}; 5 6// テンプレートの場合 7template <typename T> 8struct X { 9 static inline X x = {}; // コンパイルが通る 10};

最後の例のコンパイルはなぜ通るのでしょうか...ご回答よろしくお願い致します。

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

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

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

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

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

guest

回答2

0

「規格書のどこに書いてある」ということまでは言えませんが、推測で。

不完全型とは、オブジェクトのサイズが決定できない型のことですが、
それぞれの場合で不完全型になる理由が異なるからだと思います。
その理由とは、(1) その型を使用した時点で定義が終わっていない、(2) その型のサイズを決定することが不可能である、の2つです。

static なし・template なしの時は、(1) と (2) の両方当てはまります。
static なし・template ありの時は、(2) だけ当てはまります。
static あり・template なしの時は、(1) だけ当てはまります。
static あり・template ありの時は、どちらにも当てはまらないためエラーになりません。

template なしの時に (1) に当てはまるのは、template でないときは、X x; と書くとその時点で変数の定義になりますが、struct X の括弧の途中なので定義が終わっていないためです。
template ありの時に (1) に当てはまらないのは、template 構造体の場合は、それを使った時点で初めて実体化されるため、構造体宣言の時点では定義が終わっていなくてもいいためです。

static なしの時に (2) に当てはまるのは、メンバー変数に自分自身が含まれると、無限再帰になり、サイズを決定することができないためです。
static ありの時に (2) に当てはまらないのは、static 変数はオブジェクトのサイズに含まれないため、X のサイズは0(または処理系定義のサイズ)であると決定できるためです。

投稿2020/02/13 12:53

yuki23

総合スコア1448

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

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

alphya

2020/02/13 13:54

ご回答ありがとうございます。不完全型になる理由について、私も同じ意見です。 しかし、回答中ではコンパイルに成功すると思われる下のコードは、gcc ではコンパイルが通りますが clang と MSVC ではエラーになります。(gcc か clang & MSVC のどちらかにバグがありそうです) template <typename T> struct X { static inline auto x = X{}; // clang, MSVC でエラーになる }; 回答にあるように考えれば上のコードはコンパイルに通るはずですが、clang までエラーになるので、本当にそうなのか判断できないでいます...
guest

0

テンプレートを書いただけなら、struct Xがまだクラスとして宣言されてないので
コンパイルエラーも出ないだけだと思います
どこかでテンプレートクラスを使えば、そのときに宣言されてコンパイルエラーが出るようになると思います

投稿2020/02/13 09:59

izmktr

総合スコア2856

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

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

SaitoAtsushi

2020/02/13 10:12

私もそう思って試してみたんですが、少なくとも gcc と clang ではエラーにはならないことは確認できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問