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

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

ただいまの
回答率

90.03%

constexpr if と local struct の評価のタイミングについて

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 628

alphya

score 101

constexpr if と local struct の評価のタイミングについて

こんにちは!またよろしくお願いします!
ペコリ(o_ _)o))

初めに、次のコードはコンパイルエラーになります。case: 1
wandbox

#include <type_traits>

struct S {
    constexpr auto operator()() const -> decltype(false) {
        return false;
    }
};

template<typename T>
constexpr T get() {
    if constexpr (std::is_same_v<int, T>) return 0;
    else static_assert(S{}(), "Lambda expression is evaluated.");
}

int main() {
    get<int>();
}

つぎに、これはコンパイルが通ります。case: 2
wandbox

#include <type_traits>

template<typename T>
constexpr T get() {
    struct S {
        constexpr auto operator()() const -> decltype(false) {
            return false;
        }
    };
    if constexpr (std::is_same_v<int, T>) return 0;
    else static_assert(S{}(), "Lambda expression is evaluated.");
}

int main() {
    get<int>();
}

質問1: case: 2 の S{}() は、get()が定義される際になぜ評価されないのでしょうか。local struct S はテンプレートではないので、インスタンス化を抑制するconstexpr ifは関係なく、case: 1 と同様に評価されるのではないでしょうか...? それとも、local struct S はテンプレート引数Tに依存しているのでしょうか...

質問2: constexpr ifとtwo-phase name lookupは関係があったのでしょうか。ずっとそう思っていたのですが、constexpr ifは"テンプレート引数に依存しているものの実体化を遅延する"と考えると、名前の検索のタイミングは関係ないような気がします...。 (追記) 質問2に関して、インスタンス化されていないテンプレートはそもそも使えないので、テンプレート定義の中に依存名があってもなくても同じと考えられないでしょうか。

(追記の追記) すみません...質問2はなかったことにしてください...

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

こんにちは。

質問1: case: 2 の S{}() は、get()が定義される際になぜ評価されないのでしょうか。

case: 2のSは省略しないで記述すると、get<T>()::Sになりますので形式的にはTに依存していることになるようです。

質問2: constexpr ifとtwo-phase name lookupは関係があったのでしょうか。

テンプレート内で参照されるテンプレート引数に依存した名前の解決はtwo-phase name lookupされると理解しています。(two-phase name lookupについては良く知らないですが、アセンブラの1パス、2パスと同様な問題と理解しています。余談ですがC/C++も2パスを許せば本当に楽になるのですが...)

通常は1phase目に名前解決されます。しかし、テンプレート引数に与える「型」についてテンプレートを定義する前に全て定義されていることを必須とするのはナンセンスと思います。テンプレートを定義する前に明示的実体化的に引数を全て指定する必要がありますから。そこで、1phase目ではテンプレート引数に依存した名前は未解決であることを許しているのだと思います。

そして、2phase目はテンプレートの実体化時に行われる筈です。その際constexpr ifは条件が成立しない方の2phase目以降を実行しないということではないでしょうか?
コンパイル時に決定できるものですからそれでOKと思います。通常のif文は実行時に分岐する「建前」なので通常のif文にするとアサートします。

ああ、そうすると前回書いた「実体化を遅延する効果」とう表現は不適切でした。通常のif文でもテンプレート引数に依存したものは当然「実体化は遅延」されます。通常のif文では実体化が抑制されないので普通にアサートするわけです。
「実体化を抑制する効果」と書くべきでした。(リンク先もそう書いてありました。申し訳ないです。)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/29 18:10 編集

    Chironianさん、回答ありがとうございます!!

    質問1について、本当にありがとうございました!!
    これで、[]{return false;}() が使えます!

    (質問2については、"実体化と名前解決は違うもの"と考えていたのですが、"実体化=名前解決"と考えると確かに関係があると思いました!)←無視してください(泣)

    この度も本当にお世話になりました!!
    ヾ(●>д<)ノThank You

    キャンセル

+1

constexpr S() = default;

ちょっと余談ですが、trivialなcopy/move ctorは暗黙でconstexprになるからつけるなみたいな話を思い出しました。


普通にgetに依存する名前だと思ったんですが自信がなくなってきた・・・

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/29 18:15

    おお、それはしらなかった。

    キャンセル

  • 2018/12/29 18:18 編集

    ああ、自分の記事をよく読め案件だったでござる
    >= default/= delete 指定されたものはuser-provided
    やっぱり=default指定に加えたconstexprは冗長ですね。

    キャンセル

  • 2018/12/29 18:23

    >ctor/assgin opに対する=default指定に加えたconstexprは冗長

    調べてくださってありがとうございます!
    また機会があればよろしくお願いします!!
    ヾ(●>д<)ノThank You

    キャンセル

+1

質問1: (略)それとも、local struct S はテンプレート引数Tに依存しているのでしょうか... 

テンプレート関数に含まれるローカルクラス(およびローカル構造体)は依存名(dependent name)とみなす仕様となっています。関連する話題として CWG#1484 Unused local classes of function templates  があり、C++17言語仕様 §17.7.1 Implicit instantiation [temp.inst], Paragraph 1 には下記ノートが記載されています。

[Note: Within a template declaration, a local class (12.4) or enumeration and the members of a local class are never considered to be entities that can be separately instantiated (this includes their default arguments, noexcept-specifiers, and non-static data member initializers, if any). As a result, the dependent names are looked up, the semantic constraints are checked, and any templates used are instantiated as part of the instantiation of the entity within which the local class or enumeration is declared. -- end note]


質問2: constexpr ifとtwo-phase name lookupは関係があったのでしょうか。ずっとそう思っていたのですが、constexpr ifは"テンプレート引数に依存しているものの実体化を遅延する"と考えると、名前の検索のタイミングは関係ないような気がします...。

(質問意図を正確にくみとれていませんが)constexpr ifにより制御される文(=ifのthen/else節)のいずれがインスタンス化されるかが、同ifの条件部定数式によって決まります。two-phase name lookupとの関連でいえば、1回目の非依存名に関する探索はthen/else節の両者で行われます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/29 19:16 編集

    yohhoyさん、回答ありがとうございます!

    規格(ドラフト)のパラグラフもありがとうございます!! 欲しかった情報です...! 私も[temp.inst]は探したのですが、そのNoteのgoogle翻訳がよく分からなく、見逃してました......orz

    (質問2は、インスタンス化さえしなかったら、phase2はしてもいいのではと思っていたのですが、"phase2=インスタンス化"と考えると確かに関係ありそうでした...!)←無視してくださいorz

    調べていただいてありがとうございました!!
    またご縁がありましたらよろしくお願いいたします!
    ヾ(●>д<)ノThank You

    キャンセル

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

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる