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

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

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

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

Q&A

解決済

2回答

1474閲覧

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

wistaile

総合スコア24

C++

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

0グッド

0クリップ

投稿2020/11/12 09:18

質問

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

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

cpp

1#include <type_traits> 2 3struct Hoge { 4 using value_type = int; 5}; 6 7struct Hige { 8 using value_type = int; 9}; 10 11struct Hage {}; 12 13template <class T> 14using check = std::conjunction<std::is_same<T, Hoge>, std::is_same<typename T::value_type, int>>; 15 16int main() 17{ 18 static_assert(check<Hoge>::value); // -> 当然OK 19 static_assert(check<Hige>::value); // -> static_assertに引っかかる 20 static_assert(check<Hage>::value); // -> static_assertに引っかかるのではなく、value_typeが無いと言われる 21}

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

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

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

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

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

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

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

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

guest

回答2

0

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

cpp

1template<typename T, typename U = void> struct check: std::false_type {}; 2template<typename T> 3struct check<T, std::void_t<typename T::value_type>>: 4std::conjunction< 5 std::is_same<T, Hoge>, 6 std::is_same<typename T::value_type, int> 7> {};

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

cpp

1template<typename T> 2concept check_c = std::same_as<T, Hoge> && std::same_as<typename T::value_type, int>; 3 4static_assert(check_c<Hoge>); 5static_assert(check_c<Hige>); 6static_assert(check_c<Hage>);

なんて書けます。

投稿2020/11/12 14:31

編集2020/11/12 14:34
kazatsuyu

総合スコア158

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

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

wistaile

2020/11/12 16:49

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

0

ベストアンサー

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

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

c++

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

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

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

c++

1template <class T> 2struct check_value_type : std::is_same<typename T::value_type, int> {}; 3 4template <class T> 5using check = std::conjunction<std::is_same<T, Hoge>, check_value_type<T>>; 6 7static_assert(check<Hige>::value); // error: static assertion failed 8static_assert(check<Hage>::value); // error: static assertion failed 9

投稿2020/11/13 04:14

編集2020/11/13 04:22
yohhoy

総合スコア6191

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

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

wistaile

2020/11/14 13:49

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問