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

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

ただいまの
回答率

88.61%

テンプレートによるメタ関数の短絡評価の方法

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 253

wistaile

score 21

質問

テンプレートによるメタ関数の短絡評価の方法について質問です。

以下のコードをみてください。

#include <type_traits>

struct Hoge {
  using value_type = int;
};

struct Hige {
  using value_type = int;
};

struct Hage {};

template <class T>
using check = std::conjunction<std::is_same<T, Hoge>, std::is_same<typename T::value_type, int>>;

int main()
{
  static_assert(check<Hoge>::value); // -> 当然OK
  static_assert(check<Hige>::value); // -> static_assertに引っかかる
  static_assert(check<Hage>::value); // -> static_assertに引っかかるのではなく、value_typeが無いと言われる
}

上の3つのstatic_assertのうち下2つを「static_assertに失敗」させたいのですが、一番下はstruct内にvalue_typeの定義が無いため、"static_assetに失敗"ではなく、value_typeが存在しないというコンパイルエラーになります。

std::conjunctionは短絡評価すると書かれていたため、問題ないと思ったのですが間違っていたようです。

どのように実装すれば、typename T::value_typeの存在を評価せずに、その前段階のis_sameの時点でstd::false_typeにすることができますか?
教えて下さい...... よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+2

とりあえず思いつくのは、SFINAEを使ったこんな方法ですかね。

template<typename T, typename U = void> struct check: std::false_type {};
template<typename T>
struct check<T, std::void_t<typename T::value_type>>:
std::conjunction<
    std::is_same<T, Hoge>,
    std::is_same<typename T::value_type, int>
> {};

ちなみにC++20のコンセプトを使えば

template<typename T>
concept check_c = std::same_as<T, Hoge> && std::same_as<typename T::value_type, int>;

static_assert(check_c<Hoge>);
static_assert(check_c<Hige>);
static_assert(check_c<Hage>);

なんて書けます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/11/13 01:49

    本当にありがとうございます!
    この方法はまったく思いつきませんでした。
    コンセプトだと怒られないんですね…… 環境が許せば早く使いたい……

    キャンセル

checkベストアンサー

+1

std::conjunctionは短絡評価すると書かれていたため、問題ないと思ったのですが間違っていたようです。

std::conjunctionメタ関数は、テンプレート引数に指定したメタ関数の インスタンス化を短絡評価 します。質問中にある記述では、(2)std::is_sameメタ関数のインスタンス化が遅延評価されるのですが、その引数に指定するtypename T::value_type型はcheckメタ関数において有効な型でなければなりません。

template <class T>
using check = std::conjunction<
  std::is_same<T, Hoge>,                     // (1)
  std::is_same<typename T::value_type, int>  // (2)
>;

補助メタ関数check_value_typeを用意し、typename T::value_typeの確認タイミングを遅延させることで問題を回避できます。

Demo: https://wandbox.org/permlink/yQiK48uzmTFr5SvF

template <class T>
struct check_value_type : std::is_same<typename T::value_type, int> {};

template <class T>
using check = std::conjunction<std::is_same<T, Hoge>, check_value_type<T>>;

static_assert(check<Hige>::value);  // error: static assertion failed
static_assert(check<Hage>::value);  // error: static assertion failed

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/11/14 22:49

    ありがとうございます。
    なるほど…… インスタンス化の短絡評価の意味するところが理解できた気がします。
    結果としてインスタンス化されなくても、メタ関数の呼び出しの式は正しい必要があるわけですね。勉強になりました。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る