å¶ç´ã¨ã³ã³ã»ãã (C++20以ä¸)
- ãã®ãã¼ã¸ã¯ C++20 ã«æ¡ç¨ããã¦ããã³ã¢è¨èªã®æ©è½ã説æãã¦ãã¾ãã æ¨æºã©ã¤ãã©ãªã®ä»æ§ã§ä½¿ç¨ããã¦ããååä»ãåè¦ä»¶ã«ã¤ãã¦ã¯ååä»ãè¦ä»¶ãåç §ãã¦ãã ããã ãã®æ©è½ã® Concept TS ãã¼ã¸ã§ã³ã«ã¤ãã¦ã¯ãããåç §ãã¦ãã ããã
ã¯ã©ã¹ãã³ãã¬ã¼ãã颿°ãã³ãã¬ã¼ããããã³éãã³ãã¬ã¼ã颿° (ä¸è¬çã«ã¯ã¯ã©ã¹ãã³ãã¬ã¼ãã®ã¡ã³ã) ã¯ãå¶ç´ã¨ç´ä»ãããã¨ãã§ãã¾ãã å¶ç´ã¯ãã³ãã¬ã¼ã弿°ã«å¯¾ããå¶éãæå®ãã¾ãã ããã¯æãé©åãªé¢æ°ãªã¼ãã¼ãã¼ãããã³ãã³ãã¬ã¼ãç¹æ®åã鏿ããããã«ä½¿ç¨ãããã¨ãã§ãã¾ãã
ãã®ãããªè¦ä»¶ã®ååä»ãéåã¯ã³ã³ã»ããã¨å¼ã°ãã¾ãã ããããã®ã³ã³ã»ããã¯è¿°èªã§ãããã³ã³ãã¤ã«æã«è©ä¾¡ãããå¶ç´ã¨ãã¦ä½¿ç¨ããããã³ãã¬ã¼ãã®ã¤ã³ã¿ãã§ã¼ã¹ã®ä¸é¨ã«ãªãã¾ãã
#include <string> #include <cstddef> #include <concepts> using namespace std::literals; // ã³ã³ã»ãããHashableãã®å®£è¨ã // T åã®å¤ a ã«ã¤ãã¦ãå¼ std::hash<T>{}(a) ãã³ã³ãã¤ã«ã§ãããã®çµæã // std::size_t ã«å¤æå¯è½ã§ãããããªãä»»æã®å T ã«ãã£ã¦æºãããã¾ãã template<typename T> concept Hashable = requires(T a) { { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>; }; struct meow {}; template<Hashable T> void f(T); // å¶ç´ä»ã颿°ãã³ãã¬ã¼ãã // åãå¶ç´ãé©ç¨ããå¥ã®æ¹æ³ã // template<typename T> // requires Hashable<T> // void f(T); // // template<typename T> // void f(T) requires Hashable<T>; int main() { f("abc"s); // OKã std::string 㯠Hashable ãæºããã¾ãã f(meow{}); // ã¨ã©ã¼ã meow 㯠Hashable ãæºããã¾ããã }
å¶ç´ã®éåã¯ã³ã³ãã¤ã«æããã³ãã¬ã¼ãã®å®ä½åå¦çã®æ©æã«æ¤åºããã¾ãã ããã«ãã£ã¦ä»¥ä¸ã®ãããªã¨ã©ã¼ã¡ãã»ã¼ã¸ã容æã«å°ããã¾ãã
std::list<int> l = {3,-1,10}; std::sort(l.begin(), l.end()); //ã³ã³ã»ããã®ãªãä¸è¬çãªã³ã³ãã¤ã©ã®è¨ºæ: // invalid operands to binary expression ('std::_List_iterator<int>' and // 'std::_List_iterator<int>') // std::__lg(__last - __first) * 2); // ~~~~~~ ^ ~~~~~~~ // ... 以ä¸ã50è¡ã»ã©ã®åºå ... // //ã³ã³ã»ããã®ããä¸è¬çãªã³ã³ãã¤ã©ã®è¨ºæ: // error: cannot call std::sort with std::_List_iterator<int> // note: concept RandomAccessIterator<std::_List_iterator<int>> was not satisfied
ã³ã³ã»ããã®æå³ã¯ãæ§æçãªå¶é (å ç®æ¼ç®åãæã¤ãé åã§ããããªã©) ã§ã¯ãªããæå³çãªã«ãã´ãª (æ°å¤ãç¯å²ãæ®éã®é¢æ°ããªã©) ãã¢ãã«åãããã¨ã§ãã ISO C++ core guideline T.20 ã«ããã°ããæå³ã®ããã»ãã³ãã£ã¯ã¹ãæå®ããè½åã¯ãæ§æçãªå¶ç´ã¨ã¯å¯¾ç §çãªãçã®æ¦å¿µã表ç¾ããç¹æ§ã§ããã
ç®æ¬¡ |
[ç·¨é] ã³ã³ã»ãã
ã³ã³ã»ããã¯è¦ä»¶ã®ååä»ãéåã§ãã ã³ã³ã»ããã®å®ç¾©ã¯åå空éã¹ã³ã¼ãã«ç¾ããªããã°ãªãã¾ããã
ã³ã³ã»ããã®å®ç¾©ã¯ä»¥ä¸ã®å½¢å¼ãæã¡ã¾ãã
template < template-parameter-list >
|
|||||||||
// ã³ã³ã»ããã template <class T, class U> concept Derived = std::is_base_of<U, T>::value;
ã³ã³ã»ããã¯èªåèªèº«ãå帰çã«åç §ãããã¨ã¯ã§ãããå¶ç´ãããã¨ã¯ã§ãã¾ããã
template<typename T> concept V = V<T*>; // ã¨ã©ã¼ãå帰çãªã³ã³ã»ããã template<class T> concept C1 = true; template<C1 T> concept Error1 = true; // ã¨ã©ã¼ã C1 T ãã³ã³ã»ããã®å®ç¾©ãå¶ç´ãããã¨ãã¦ãã¾ãã template<class T> requires C1<T> concept Error2 = true; // ã¨ã©ã¼ã requires ç¯ãã³ã³ã»ãããå¶ç´ãããã¨ãã¦ãã¾ãã
ã³ã³ã»ããã®æç¤ºçå®ä½åãæç¤ºçç¹æ®åãé¨åç¹æ®åã¯ã§ãã¾ãã (å¶ç´ã®å ã®å®ç¾©ã®æå³ã¯å¤æ´ã§ãã¾ãã)ã
ã³ã³ã»ããã¯èå¥åå¼ã§æå®ãããã¨ãã§ãã¾ãã å¶ç´å¼ãæºããããå ´åã¯ãèå¥åå¼ã®å¤ã¯ trueãããã§ãªããã° false ã§ãã ã³ã³ã»ããã¯ä»¥ä¸ã®ä¸é¨ã¨ãã¦åå¶ç´ã§æå®ãããã¨ãã§ãã¾ãã
[ç·¨é] å¶ç´
å¶ç´ã¯ãã³ãã¬ã¼ã弿°ã«å¯¾ããè¦ä»¶ãæºããè«çæ¼ç®åã¨è¢«æ¼ç®åã®ä¸¦ã³ã§ãã ããã㯠requires å¼ (å¾è¿°) å ã§ãããã³ã³ã³ã»ããã®æ¬ä½ã¨ãã¦ç´æ¥ãç¾ãããã¨ãã§ãã¾ãã
3種é¡ã®å¶ç´ãããã¾ãã
宣è¨ã«ç´ä»ããããå¶ç´ã¯è¢«æ¼ç®åã以ä¸ã®é åºã§ããè«çç©å¼ãæ£è¦åãããã¨ã«ãã£ã¦æ±ºå®ããã¾ãã
- ããããã®å¶ç´ä»ããã³ãã¬ã¼ã弿°ã«å¯¾ãã¦å°å ¥ãããå¶ç´å¼ (åºç¾é )ã
- ãã³ãã¬ã¼ã弿°ãªã¹ãã®å¾ã® requires ç¯ã®å¶ç´å¼ã
- å¾ç½® requires ç¯ã®å¶ç´å¼ã
ãã®é åºã¯æºãããã©ããããã§ãã¯ããã¨ãã«å¶ç´ãå®ä½åãããé åºã決å®ãã¾ãã
å¶ç´ä»ã宣è¨ã¯åãæ§æå½¢å¼ãç¨ãã¦ã®ã¿å宣è¨ãã¦ãæ§ãã¾ããã 診æã¯è¦æ±ããã¾ããã
template<Incrementable T> void f(T) requires Decrementable<T>; template<Incrementable T> void f(T) requires Decrementable<T>; // OKãå宣è¨ã template<typename T> requires Incrementable<T> && Decrementable<T> void f(T); // ill-formed (診æã¯è¦æ±ããã¾ãã)ã // 以ä¸ã®2ã¤ã®å®£è¨ã¯ç°ãªãå¶ç´ãæã¡ã¾ã // (ãã¨ãè«ççã«ã¯åçã§ãã£ã¦ã)ã // 1ã¤ãã®å®£è¨ã¯ Incrementable<T> && Decrementable<T> ã§ããã // 2ã¤ãã®å®£è¨ã¯ Decrementable<T> && Incrementable<T> ã§ãã template<Incrementable T> void g(T) requires Decrementable<T>; template<Decrementable T> void g(T) requires Incrementable<T>; // ill-formed (診æã¯è¦æ±ããã¾ãã)ã
[ç·¨é] è«çç©
2ã¤ã®å¶ç´ã®è«çç©ã¯å¶ç´å¼å
ã§ &&
æ¼ç®åãç¨ãããã¨ã«ãã£ã¦å½¢æããã¾ãã
template <class T> concept Integral = std::is_integral<T>::value; template <class T> concept SignedIntegral = Integral<T> && std::is_signed<T>::value; template <class T> concept UnsignedIntegral = Integral<T> && !SignedIntegral<T>;
2ã¤ã®å¶ç´ã®è«çç©ã¯ä¸¡æ¹ã®å¶ç´ãæºããããå ´åã«ã®ã¿æºãããã¾ãã è«çç©ã¯å·¦ããå³ã«è©ä¾¡ãããç絡è©ä¾¡ããã¾ã (å·¦ã®å¶ç´ãæºããããªãå ´åã¯ãå³ã®å¶ç´ã¸ã®ãã³ãã¬ã¼ã弿°ã®ç½®ãæãã¯è©¦ã¿ããã¾ããã ããã¯ç´æ¥ã®æèã®å¤å´ã®ç½®æã«ãã失æãé²ãã¾ã)ã
template<typename T> constexpr bool get_value() { return T::value; } template<typename T> requires (sizeof(T) > 1 && get_value<T>()) void f(T); // #1 void f(int); // #2 void g() { f('A'); // OKã #2 ãå¼ã³ã¾ãã #1 ã®å¶ç´ããã§ãã¯ããã¨ã // ãsizeof(char) > 1ãã¯æºããããªãããã get_value<T>() ã¯ãã§ãã¯ããã¾ããã }
[ç·¨é] è«çå
2ã¤ã®å¶ç´ã®è«çåã¯å¶ç´å¼å
ã§ ||
æ¼ç®åãç¨ãããã¨ã«ãã£ã¦å½¢æããã¾ãã
2ã¤ã®å¶ç´ã®è«çåã¯ããããã®å¶ç´ãæºããããå ´åã«æºãããã¾ãã è«çåã¯å·¦ããå³ã«è©ä¾¡ãããç絡è©ä¾¡ããã¾ã (å·¦ã®å¶ç´ãæºããããå ´åã¯ãå³ã®å¶ç´ã¸ã®ãã³ãã¬ã¼ã弿°ã®ç½®ãæãã¯è©¦ã¿ããã¾ãã)ã
template <class T = void> requires EqualityComparable<T> || Same<T, void> struct equal_to;
[ç·¨é] ååå¶ç´
ååå¶ç´ã¯ãå¼ E
ã¨ãå¶ç´ãããã¨ã³ãã£ãã£ã®ãã³ãã¬ã¼ã仮弿°ã«å½±é¿ãã E
å
ã«ç¾ãããã³ãã¬ã¼ã仮弿°ãããã³ãã¬ã¼ãå®å¼æ°ã¸ã®ãããã³ã° (弿°ãããã³ã°ã¨è¨ãã¾ã) ãããæ§æããã¾ãã
ååå¶ç´ã¯å¶ç´ã®æ£è¦åä¸ã«å½¢æããã¾ãã E
ãè«çç©å¼ã¾ãã¯è«çåå¼ã§ãããã¨ã¯ããã¾ãã (ãããã¯ããããè«çç©ããã³è«çåãå½¢æãã¾ã)ã
ååå¶ç´ãæºãããã©ããã¯ã弿°ãããã³ã°ã¨ãã³ãã¬ã¼ãå®å¼æ°ãå¼ E
å
ã«ç½®ãæãããã¨ã«ãã£ã¦ãã§ãã¯ããã¾ãã ç½®ãæãã®çµæãç¡å¹ãªåã¾ãã¯å¼ã¨ãªã£ãå ´åã¯ããã®å¶ç´ã¯æºãããã¾ããã ããã§ãªããã°ããããã左辺å¤ããå³è¾ºå¤ã¸ã®å¤æã®å¾ã E
㯠bool åã® prvalue 宿°å¼ã§ãªããã°ãªãããããã true
ã«è©ä¾¡ãããå ´åã«éãããã®å¶ç´ãæºãããã¾ãã
ç½®ãæãå¾ã® E
ã®åã¯æ£ç¢ºã« bool ã§ãªããã°ãªãã¾ããã 夿ã¯èªãããã¾ããã
template<typename T> struct S { constexpr operator bool() const { return true; } }; template<typename T> requires (S<T>{}) void f(T); // #1 void f(int); // #2 void g() { f(0); // ã¨ã©ã¼ã #1 ããã§ãã¯ããã¨ãã S<int>{} ã bool åã§ã¯ããã¾ããã // ãã¨ã #2 ãããè¯ããããã§ãã£ãã¨ãã¦ãã }
2ã¤ã®ååå¶ç´ã¯ãããããã½ã¼ã¹ã¬ãã«ã§åãå¼ããå½¢æããããã®å¼æ°ãããã³ã°ãåçãªå ´åãåä¸ã§ããã¨ã¿ãªããã¾ãã
template<class T> constexpr bool is_meowable = true; template<class T> constexpr bool is_cat = true; template<class T> concept Meowable = is_meowable<T>; template<class T> concept BadMeowableCat = is_meowable<T> && is_cat<T>; template<class T> concept GoodMeowableCat = Meowable<T> && is_cat<T>; template<Meowable T> void f1(T); // #1 template<BadMeowableCat T> void f1(T); // #2 template<Meowable T> void f2(T); // #3 template<GoodMeowableCat T> void f2(T); // #4 void g(){ f1(0); // ã¨ã©ã¼ãææ§ã§ãã // Meowable 㨠BadMeowableCat ã® is_meowable<T> ã¯ãåä¸ã§ãªã // ç°ãªãååå¶ç´ãå½¢æãã¾ã (ãã®ãããäºãã«å å«ãã¾ãã)ã f2(0); // OKã #3 ããå¤ãå¶ç´ããã¦ãã #4 ãå¼ã³ã¾ãã // GoodMeowableCat 㯠Meowable ãã is_meowable<T> ãå¾ã¦ãã¾ãã }
[ç·¨é] å¶ç´ã®æ£è¦å
å¶ç´ã®æ£è¦åã¯å¶ç´å¼ãååå¶ç´ã®è«çç©ã¨è«çåã®ä¸¦ã³ã«å¤æããå¦çã§ãã å¼ã®æ£è¦å½¢ã¯ä»¥ä¸ã®ããã«å®ç¾©ããã¾ãã
- å¼ (E) ã®æ£è¦å½¢ã¯ E ã®æ£è¦å½¢ã§ãã
- å¼ E1 && E2 ã®æ£è¦å½¢ã¯ E1 㨠E2 ã®æ£è¦å½¢ã®è«çç©ã§ãã
- å¼ E1 || E2 ã®æ£è¦å½¢ã¯ E1 㨠E2 ã®æ£è¦å½¢ã®è«çåã§ãã
- å¼ C<A1, A2, ... , AN> (
C
ãã³ã³ã»ããã表ãå ´å) ã®æ£è¦å½¢ã¯ãC
ã®ããããã®ãã³ãã¬ã¼ã弿°ã«ã¤ãã¦ã C ã®ããããã®ååå¶ç´ã®å¼æ°ãããã³ã°ã§ A1, A2, ... , AN ãç½®ãæããå¾ã®ãC
ã®å¶ç´å¼ã®æ£è¦å½¢ã§ãã 弿°ãããã³ã°ã¸ã®ãã®ãããªç½®ãæãã®ããããã®çµæãç¡å¹ãªåã¾ãã¯å¼ã¨ãªã£ãå ´åã¯ãããã°ã©ã 㯠ill-formed ã§ã (診æã¯è¦æ±ããã¾ãã)ã
template<typename T> concept A = T::value || true; template<typename U> concept B = A<U*>; // OKã以ä¸ã®è«çåã«æ£è¦åããã¾ãã // ã»T::value (T â U* ã®ãããã³ã°ãæã¡ã¾ã) // ã»true (空ã®ãããã³ã°ãæã¡ã¾ã) // ãã¨ããã¹ã¦ã®ãã¤ã³ã¿åã«ã¤ã㦠T::value ã ill-formed ã§ãã£ã¦ãã // ãããã³ã°å ã«ç¡å¹ãªåã¯ããã¾ããã template<typename V> concept C = B<V&>; // 以ä¸ã®è«çåã«æ£è¦åããã¾ãã // ã»T::value (T â V&* ã®ãããã³ã°ãæã¡ã¾ã) // ã»true (空ã®ãããã³ã°ãæã¡ã¾ã) // ãããã³ã°å ã«å½¢æãããç¡å¹ãªå V&* â ill-formed (診æã¯è¦æ±ããã¾ãã)ã
- ãã以å¤ã®ããããå¼ E ã®æ£è¦å½¢ã¯ãå¼ã E ã§ãã弿°ãããã³ã°ãæçãããã³ã°ã§ããååå¶ç´ã§ãã ããã«ã¯ãã¹ã¦ã®ç³ã¿è¾¼ã¿å¼ãå«ã¾ãã¾ã (ãã¨ã
&&
ã¾ãã¯||
æ¼ç®åã®ç³ã¿è¾¼ã¿ã§ãã£ã¦ã)ã
&&
ã¾ã㯠||
ã®ã¦ã¼ã¶å®ç¾©ãªã¼ãã¼ãã¼ãã¯å¶ç´ã®æ£è¦åã«ããã¦å¹æãæã¡ã¾ããã
[ç·¨é] requires ç¯
ãã¼ã¯ã¼ã requires 㯠requires ç¯ãå°å ¥ããããã«ä½¿ç¨ããã¾ãã ããã¯ãã³ãã¬ã¼ã弿°ã¾ãã¯é¢æ°å®£è¨ã«ããã¦å¶ç´ãæå®ãã¾ãã
template<typename T> void f(T&&) requires Eq<T>; // 颿°å®£è¨åã®æå¾ã®è¦ç´ ã¨ãã¦ç¾ãããã¨ãã§ãã¾ãã template<typename T> requires Addable<T> // ã¾ãã¯ãã³ãã¬ã¼ã弿°ãªã¹ãã®ç´å¾ã«ç¾ãããã¨ãã§ãã¾ãã T add(T a, T b) { return a + b; }
ãã®å ´åããã¼ã¯ã¼ã requires ã¯ä½ããã®å®æ°å¼ãå¾ã«ç¶ããªããã°ãªãã¾ãã (ãã®ãã requires true ã¨æ¸ããã¨ãã§ãã¾ã) ãããã®æå³ã¯ååä»ãã³ã³ã»ãã (ä¸ã®ä¾ã®ããã«) ã¾ãã¯ååä»ãã³ã³ã»ããã®è«çç©/è«çåã¾ã㯠requires å¼ã使ç¨ãããã¨ã§ãã
å¼ã¯ä»¥ä¸ã®å½¢å¼ã®ããããã§ãªããã°ãªãã¾ããã
- 䏿¬¡å¼ãä¾ãã° Swappable<T>ã std::is_integral<T>::valueã (std::is_object_v<Args> && ...)ãã¾ãã¯æ¬å¼§ã§å²ã¾ããããããå¼ã
- æ¼ç®å
&&
ã§é£çµããã䏿¬¡å¼ã®ä¸¦ã³ã - æ¼ç®å
||
ã§é£çµãããä¸ã®ããããã®å¼ã®ä¸¦ã³ã
template<class T> constexpr bool is_meowable = true; template<class T> constexpr bool is_purrable() { return true; } template<class T> void f(T) requires is_meowable<T>; // OKã template<class T> void g(T) requires is_purrable<T>(); // ã¨ã©ã¼ã is_purrable<T>() ã¯ä¸æ¬¡å¼ã§ã¯ããã¾ããã template<class T> void h(T) requires (is_purrable<T>()); // OKã
[ç·¨é] requires å¼
ãã¼ã¯ã¼ã requires 㯠requires å¼ãéå§ããããã«ä½¿ç¨ãããã¨ãã§ãã¾ãã ããã¯ããã¤ãã®ãã³ãã¬ã¼ã弿°ã«å¯¾ããå¶ç´ãè¨è¿°ãã bool åã® prvalue å¼ã§ãã ãã®ãããªå¼ã¯ãå¶ç´ãæºããããå ´å㯠true
ãããã§ãªããã° false
ã§ãã
template<typename T> concept Addable = requires (T x) { x + x; }; // requires å¼ã template<typename T> requires Addable<T> // requires ç¯ (requires å¼ã§ã¯ããã¾ãã)ã T add(T a, T b) { return a + b; } template<typename T> requires requires (T x) { x + x; } // ã¢ãããã¯å¶ç´ (ãã¼ã¯ã¼ãã2å使ç¨ããã¦ãããã¨ã«æ³¨æãã¦ãã ãã)ã T add(T a, T b) { return a + b; }
requires å¼ã®æ§æã¯ä»¥ä¸ã®éãã§ãã
requires { requirement-seq }
|
|||||||||
requires ( parameter-list(ãªãã·ã§ã³) ) { requirement-seq }
|
|||||||||
parameter-list | - | 颿°å®£è¨ã¨åæ§ã®å¼æ°ã®ã³ã³ãåºåãã®ãªã¹ãã ãã ãããã©ã«ã弿°ã¯ä½¿ç¨ã§ãããçç¥è¨å· (ããã¯å±éã表ããã®ä»¥å¤) ã§çµãããã¨ã¯ã§ãã¾ããã ãããã®å¼æ°ã¯ãè¨æ¶åããªã³ã±ã¼ã¸ãçåæéãæãããè¦ä»¶ã®æå®ãè£å©ããããã«ã®ã¿ä½¿ç¨ããã¾ãã ãããã®å¼æ°ã¯ requirement-seq ã®éãæ¬å¼§ } ã¾ã§ãã¹ã³ã¼ãå
ã§ãã
|
requirement-seq | - | è¦ä»¶ã®ä¸¦ã³ã ä¸ã§èª¬æããã¾ã (ããããã®è¦ä»¶ã¯ã»ãã³ãã³ã§çµããã¾ã)ã |
requirements-seq å ã®ããããã®è¦ä»¶ã¯ä»¥ä¸ã®ããããã§ãã
- åç´è¦ä»¶ã
- åè¦ä»¶ã
- è¤åè¦ä»¶ã
- ãã¹ãããè¦ä»¶ã
è¦ä»¶ã¯ã¹ã³ã¼ãå ã®ãã³ãã¬ã¼ã弿°ã parameter-list ã§å°å ¥ããããã¼ã«ã«ãªå¼æ°ãããã³å²ã£ã¦ããæèããå¯è¦ãªãã®ä»ã®ä»»æã®å®£è¨ãåç §ãã¦ãæ§ãã¾ããã
ãã³ãã¬ã¼ãåãããã¨ã³ãã£ãã£ã®å®£è¨ã§ä½¿ç¨ããã requires å¼å ã¸ã®ãã³ãã¬ã¼ã弿°ã®ç½®ãæãã®çµæããã®è¦ä»¶å ã§ç¡å¹ãªåãå¼ãå½¢æãããããããã®è¦ä»¶ã®æå³å¶ç´ã®éåã¨ãªããã¨ãããã¾ãã ãã®ãããªå ´åã requires å¼ã¯ false ã«è©ä¾¡ãããããã°ã©ã ã ill-formed ã«ã¯ãã¾ããã ç½®ãæãã¨æå³å¶ç´ã®ãã§ãã¯ã¯åå¥é ã«é²è¡ãã requires å¼ã®çµæã決å®ããæ¡ä»¶ã«ééããã¨ãã«åæ¢ãã¾ãã ç½®ãæã (ããããã°) ããã³æå³å¶ç´ã®ãã§ãã¯ãæåããå ´åã requires å¼ã¯ true ã«è©ä¾¡ããã¾ãã
ãã¹ã¦ã®æãå¾ããã³ãã¬ã¼ã弿°ã«ã¤ã㦠requires å¼ã§ç½®ãæãã®å¤±æãçºçããã§ãããå ´åãããã°ã©ã 㯠ill-formed ã§ã (診æã¯è¦æ±ããã¾ãã)ã
template<class T> concept C = requires { new int[-(int)sizeof(T)]; // ãããã T ã«å¯¾ãã¦ç¡å¹ã ill-formed ã§ã (診æã¯è¦æ±ããã¾ãã)ã };
requires å¼ããã®è¦ä»¶ã«ç¡å¹ãªåã¾ãã¯å¼ãå«ã¿ããã³ãã¬ã¼ãåãããã¨ã³ãã£ãã£å ã«ãããç¾ããªãå ´åãããã°ã©ã 㯠ill-formed ã§ãã
[ç·¨é] åç´è¦ä»¶
åç´è¦ä»¶ã¯ä»»æã®å¼æã§ãã ãã®å¼ãæå¹ã§ãããã¨ã表æãã¾ãã å¼ã¯æªè©ä¾¡è¢«æ¼ç®åã§ãã è¨èªã®æ£ããã®ã¿ããã§ãã¯ããã¾ãã
template<typename T> concept Addable = requires (T a, T b) { a + b; // ãå¼ a + b ã¯ã³ã³ãã¤ã«ã§ããæå¹ãªå¼ã§ããã }; template <class T, class U = T> concept Swappable = requires(T&& t, U&& u) { swap(std::forward<T>(t), std::forward<U>(u)); swap(std::forward<U>(u), std::forward<T>(t)); };
[ç·¨é] åè¦ä»¶
åè¦ä»¶ã¯ãã¼ã¯ã¼ã typename ã«åå (修飾ããã¦ãã¦ãæ§ãã¾ãã) ãç¶ãããã®ã§ãã ãã®è¦ä»¶ã¯æå®ãããåãæå¹ã§ãããã¨ã§ãã ããã¯ç¹å®ã®ååã®ãã¹ãããåãåå¨ãããã¨ããã¯ã©ã¹ãã³ãã¬ã¼ãã®ç¹æ®åãåã表ããã¨ããã¨ã¤ãªã¢ã¹ãã³ãã¬ã¼ãã®ç¹æ®åãåã表ããã¨ãæ¤è¨¼ããããã«ä½¿ç¨ãããã¨ãã§ãã¾ãã ã¯ã©ã¹ãã³ãã¬ã¼ãã®ç¹æ®åãæå®ããåè¦ä»¶ã¯ããã®åãå®å ¨åã§ãããã¨ãè¦æ±ãã¾ããã
template<typename T> using Ref = T&; template<typename T> concept C = requires { typename T::inner; // è¦æ±ããããã¹ãããã¡ã³ãã®ååã typename S<T>; // è¦æ±ãããã¯ã©ã¹ãã³ãã¬ã¼ãã®ç¹æ®åã typename Ref<T>; // è¦æ±ãããã¨ã¤ãªã¢ã¹ãã³ãã¬ã¼ãã®ç½®ãæãã }; template <class T, class U> using CommonType = std::common_type_t<T, U>; template <class T, class U> concept Common = requires (T t, U u) { typename CommonType<T, U>; // CommonType<T, U> ãæå¹ã§ãããåã表ãã { CommonType<T, U>{std::forward<T>(t)} }; { CommonType<T, U>{std::forward<U>(u)} }; };
[ç·¨é] è¤åè¦ä»¶
è¤åè¦ä»¶ã¯ä»¥ä¸ã®å½¢å¼ãæã¡ãæå®ãããå¼ã®æ§è³ªã表æãã¾ãã
{ expression } noexcept (ãªãã·ã§ã³) return-type-requirement(ãªãã·ã§ã³) ;
|
|||||||||
return-type-requirement | - | -> type-constraint
|
ç½®ãæãããã³æå³å¶ç´ã®ãã§ãã¯ã¯ä»¥ä¸ã®é åºã§é²è¡ãã¾ãã
noexcept
ã使ç¨ããã¦ããå ´åã¯ã expression ã¯æ½å¨çã«ä¾å¤ãæãã¦ã¯ãªãã¾ãããtemplate<typename T> concept C2 = requires(T x) { {*x} -> std::convertible_to<typename T::inner>; // å¼ *x ãæå¹ã§ãªããã°ãªããã // ããã«ãå T::inner ãæå¹ã§ãªããã°ãªããã // ããã«ã *x ã®çµæã T::inner ã«å¤æå¯è½ã§ãªããã°ãªãã¾ããã {x + 1} -> std::same_as<int>; // å¼ X + 1 ãæå¹ã§ãªããã°ãªããã // ããã«ã std::Same<decltype((x + 1)), int> ãæºããããªããã°ãªãã¾ããã // ããªãã¡ã (x + 1) 㯠int åã® prvalue ã§ãªããã°ãªãã¾ããã {x * 1} -> std::convertible_to<T>; // å¼ x * 1 ãæå¹ã§ãªããã°ãªããã // ããã«ããã®çµæã T ã«å¤æå¯è½ã§ãªããã°ãªãã¾ããã };
[ç·¨é] ãã¹ãããè¦ä»¶
ãã¹ãããè¦ä»¶ã¯ä»¥ä¸ã®å½¢å¼ãæã¡ã¾ãã
requires constraint-expression ;
|
|||||||||
ããã¯ãã¼ã«ã«ãªå¼æ°ãç¨ãã追å ã®å¶ç´ãæå®ããããã«ä½¿ç¨ã§ãã¾ãã constraint-expression ã¯ç½®ãæãããããã³ãã¬ã¼ã弿°ã«ãã£ã¦æºããããªããã°ãªãã¾ããã ãã¹ãããè¦ä»¶ã¸ã®ãã³ãã¬ã¼ã弿°ã®ç½®ãæãã¯ã constraint-expression ãæºãããããã©ãããæ±ºå®ããããã«å¿ è¦ã¨ãããç¯å²ã«ã®ã¿ constraint-expression ã¸ã®ç½®ãæããçºçããã¾ãã
template <class T> concept Semiregular = DefaultConstructible<T> && CopyConstructible<T> && Destructible<T> && CopyAssignable<T> && requires(T a, size_t n) { requires Same<T*, decltype(&a)>; // ãã¹ãããè¦ä»¶ãSame<...> ã true ã«è©ä¾¡ãããã { a.~T() } noexcept; // è¤åè¦ä»¶ãa.~T() ãæå¹ãªå¼ã§ããä¾å¤ãæããªãã requires Same<T*, decltype(new T)>; // ãã¹ãããè¦ä»¶ãSame<...> ã true ã«è©ä¾¡ãããã requires Same<T*, decltype(new T[n])>; // ãã¹ãããè¦ä»¶ { delete new T }; // è¤åè¦ä»¶ { delete new T[n] }; // è¤åè¦ä»¶ };
[ç·¨é] å¶ç´ã®åé åº
ãããªããã以ä¸ã®è§£æãããåã«ãæ®ã£ã¦ãããã®ãååå¶ç´ã«å¯¾ããè«çç©ã¨è«çåã®ä¸¦ã³ã«ãªãã¾ã§ããã¹ã¦ã®ååã³ã³ã»ããããã³ãã¹ã¦ã® requires å¼ã®æ¬ä½ãç½®ãæãããã¨ã«ãã£ã¦ãå¶ç´ãæ£è¦åããã¾ãã
P ããã³ Q å
ã®ååå¶ç´ã®å䏿§ã«è³ãã¾ã§ P
ã Q
ãå«ããã¨ã証æã§ããå ´åãå¶ç´ P
ã¯å¶ç´ Q
ãå
å«ããã¨è¨ãã¾ã (åããã³å¼ã¯åçæ§ã«ã¤ãã¦è§£æããã¾ããã N > 0
㯠N >= 0
ãå
å«ãã¾ãã)ã
å
·ä½çã«ã¯ãã¾ã P
ãè«ç忣è¦å½¢ã«å¤æããã Q
ãè«çç©æ£è¦å½¢ã«å¤æããã¾ãã 以ä¸ã®å ´åã«éãã P
㯠Q
ãå
å«ãã¾ãã
-
P
ã®è«ç忣è¦å½¢ã®ãã¹ã¦ã®è«çåç¯ããQ
ã®è«çç©æ£è¦å½¢ã®ãã¹ã¦ã®è«çç©ç¯ãå å«ããã ãã ãã -
U
ãV
ãå å«ãããããªè«çåç¯å ã®ååå¶ç´U
ããã³è«çç©ç¯å ã®ååå¶ç´V
ãåå¨ããå ´åã«éããè«çåç¯ã¯è«çç©ç¯ãå å«ãã¾ãã - ä¸ã§èª¬æãã¦ããã«ã¼ã«ãç¨ãã¦åä¸ã§ããå ´åã«éããååå¶ç´
A
ã¯ååå¶ç´B
ãå å«ãã¾ãã
å å«é¢ä¿ã¯å¶ç´ã®åé åºãå®ç¾©ãã¾ãã ããã¯ä»¥ä¸ã®ãã®ã決å®ããããã«ä½¿ç¨ããã¾ãã
- ãªã¼ãã¼ãã¼ã解決ã«ãããéãã³ãã¬ã¼ã颿°ã«å¯¾ããæé©åè£ã
- ãªã¼ãã¼ãã¼ãéåå ã®éãã³ãã¬ã¼ã颿°ã®ã¢ãã¬ã¹ã
- ãã³ãã¬ã¼ããã³ãã¬ã¼ã弿°ã«å¯¾ãããã¹ããããã
- ã¯ã©ã¹ãã³ãã¬ã¼ãã®ç¹æ®åã®åé åºã
- 颿°ãã³ãã¬ã¼ãã®åé åºã
This section is incomplete Reason: backlinks from the above to here |
å®£è¨ D1
ããã³ D2
ãå¶ç´ä»ãã§ããã D1 ã«ç´ä»ãå¶ç´ã D2 ã«ç´ä»ãå¶ç´ãå
å«ãã (ã¾ã㯠D2 ãå¶ç´ä»ãã§ãªã) å ´åã D1 㯠D2 ã¨å°ãªãã¨ãåç¨åº¦ã«å¶ç´ããã¦ããã¨è¨ãã¾ãã D1 ã D2 ã¨å°ãªãã¨ãåç¨åº¦ã«å¶ç´ããã¦ããã D2 ã D1 ã¨å°ãªãã¨ãåç¨åº¦ã«å¶ç´ããã¦ããªãå ´åã D1 㯠D2 ããå¤ãå¶ç´ããã¦ãã¾ãã
template<typename T> concept Decrementable = requires(T t) { --t; }; template<typename T> concept RevIterator = Decrementable<T> && requires(T t) { *t; }; // RevIterator 㯠Decrementable ãå å«ãã¾ãããéæ¹åã«ã¯å å«ãã¾ãã template<Decrementable T> void f(T); // #1 template<RevIterator T> void f(T); // #2 (#1 ããå¤ãå¶ç´ããã¦ãã¾ã) f(0); // int 㯠Decrementable ã®ã¿ãæºããã¾ãã #1 ã鏿ããã¾ãã f((int*)0); // int* ã¯ã©ã¡ãã®å¶ç´ãæºããã¾ãã ããå¤ãå¶ç´ããã¦ãããã #2 ã鏿ããã¾ãã template<class T> void g(T); // #3 (å¶ç´ãªã) template<Decrementable T> void g(T); // #4 g(true); // bool 㯠Decrementable ãæºããã¾ããã #3 ã鏿ããã¾ãã g(0); // int 㯠Decrementable ãæºããã¾ãã ããå¤ãå¶ç´ããã¦ãããã #4 ã鏿ããã¾ãã template<typename T> concept RevIterator2 = requires(T t) { --t; *t; }; template<Decrementable T> void h(T); // #5 template<RevIterator2 T> void h(T); // #6 h((int*)0); // ææ§ã§ãã