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

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

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

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

Q&A

解決済

2回答

1538閲覧

requires式を簡潔に書きたい

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

0クリップ

投稿2020/11/02 15:52

編集2020/11/02 16:17

質問内容

c++20のrequires式の定義にまつわる質問です。
下記コード1はidentification関数の引数に
入力した値の型が構造体Hogeの場合
標準出力に"Hogeです"と表示し、
Hogeでない場合は"Hogeではない"
と表示するプログラムです。

その中のidentification関数では引数で使用されている
コンセプトのHogeConceptでは
構造体Hogeのメンバであるfuga関数(引数、戻り値ともに整数全般)があるかどうかで
引数(HogeConcept auto const&)がHogeかどうかを判別し
型の入力制限を行います。

しかしコード1ではHogeConceptの定義部分が長くなってしまいます。
整数型全般を表せる型を書けることができたとしたら
下記コード2のように1行で済ませることができそうなのですが
そのような型を書くことができるのでしょうか。

ちなみに私はコード3のように書けば良いのではないかと考え
書いてみましたが

error: 'auto' not allowed in template argument

(エラー:「auto」はテンプレート引数では許可されていません)

とコンパイルエラーを吐いてしまい動きませんでした。

御回答どうか宜しくお願い致します。

注意:
identification関数を下記コード4のように書けばHogeConceptを
書かずに済むが、本質問ではこのような方法は用いないものとする。

コード1

c++

1#include <iostream> 2#include <concepts> 3#include <utility> 4 5template<typename Type> 6concept HogeConcept = requires(Type t1){// template引数やautoの型をHogeと推論させるためのコンセプト 7 {t1.fuga(short())} -> std::integral<>; 8 {t1.fuga(std::declval<unsigned short>())} -> std::integral<>; 9 10 {t1.fuga(int())} -> std::integral<>; 11 {t1.fuga(std::declval<unsigned int>())} -> std::integral<>; 12 13 {t1.fuga(long())} -> std::integral<>; 14 {t1.fuga(std::declval<unsigned long>())} -> std::integral<>; 15 16 {t1.fuga(std::declval<long long>())} -> std::integral<>; 17 {t1.fuga(std::declval<unsigned long long>())} -> std::integral<>; 18 19}; 20 21struct Hoge{ 22 template<std::integral Type> 23 Type fuga(const Type arg){return arg;} 24}; 25 26void identification(HogeConcept auto const&){// 引数がHogeのオブジェクトの場合実行 27 std::cout << "Hogeです" << std::endl; 28} 29 30void identification(...){// 引数がHogeのオブジェクト以外の場合実行 31 std::cout << "Hogeではない" << std::endl; 32} 33 34int main(){ 35 auto hoge = Hoge(); 36 37 identification(hoge); 38 identification(int()); 39 40 return 0; 41}

実行結果

terminal

1Hogeです 2Hogeではない

コード2

c++

1template<typename Type> 2concept HogeConcept = requires(Type t1){ 3 {t1.fuga([整数型全般を表せる型])} -> std::integral<>; 4};

コード3

c++

1template<typename Type> 2concept HogeConcept = requires(Type t1){ 3 {t1.fuga(std::declval<std::integral auto>())} -> std::integral<>; 4};

コード4

c++

1void identification(std::same_as<Hoge> auto const&){ 2 std::cout << "Hogeです" << std::endl; 3}

開発環境の備考

種類名前バージョン備考
osLinux Mint20-
コンパイラclang++10本文中のコードをコンパイルする時オプションに-std=c++2aを指定

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

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

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

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

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

guest

回答2

0

ベストアンサー

えー、やや曖昧な回答になりますが、コンセプトは集合で捉えることができます(ここ何か突っ込み入りそう)が、基本的には無限集合として扱われます。コンセプトの定義によってはそれを満たす型が有限集合である可能性はありますが、それが有限かどうかを保証する術はありません。コンセプトが有限であるか否かを確かめることと停止性問題を解くことが同等の問題になるはずです(ホンマか?)(ちょっと突っ込みが欲しい)。

つまり、 std::integral を満たす型は無限に存在する可能性があり(もちろん計算機のリソースの限界があるので実際には無限にはなり得ませんが)、

cpp

1{t1.fuga([整数型全般を表せる型])} -> std::integral<>;

のようなチェックを行うには std::integral を満たす可能性のある全ての(無限の)型に対して std::integral を満たすかどうかのチェックと t1.fuga が呼び出せるかどうかのチェックを行う必要がありますが、これは不可能です。

投稿2020/11/03 03:29

kazatsuyu

総合スコア158

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

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

退会済みユーザー

退会済みユーザー

2020/11/03 21:55

kazatsuyuさん 不可能であることが分かり良かったです。 御回答誠にありがとうございました。
guest

0

具体的な型が確定するときにそれが性質を満たすかどうかをチェックする機構がコンセプトです。

どこかで型が陽に与えられるか推論可能である必要があり、プログラム中のどこにも具体的な型が存在しないときに整数型全般を抽象化した型で表すということは出来ません。

投稿2020/11/03 03:27

SaitoAtsushi

総合スコア5444

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

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

退会済みユーザー

退会済みユーザー

2020/11/03 21:55

SaitoAtsushiさん 不可能であることが分かり良かったです。 御回答誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問