Outils pour utilisateurs

Outils du site


lang:cpp:concept

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
lang:cpp:concept [2020/02/05 21:58] – Création rootlang:cpp:concept [2021/11/13 09:04] (Version actuelle) – Ajout de "Restriction" "Fonction template" root
Ligne 5: Ligne 5:
 ====Définitions des concepts==== ====Définitions des concepts====
  
-Contrainte sur un type :+  * Contrainte sur un type :
  
 <code cpp> <code cpp>
Ligne 12: Ligne 12:
 </code> </code>
  
-Contrainte sur les fonctions :+  * Contrainte sur les fonctions :
  
 <code cpp> <code cpp>
-// look, this concept requires two types +template <typename T> 
-template <typename X, typename Y+// Le type est cv. Donc, il faut utiliser deux paramètres, l'un pour const, l'autre sans. 
-concept they_are_mathsy = requires(X xY y)+concept Shape = requires(const T t, T ufloat f)
 { {
-    { x * y }; +  // Le type de retour est facultatif mais conseillé. 
-    x / y }; +  t.area() -> std::same_as<float>
-    x + y }; +  u.mod(f) -> std::same_as<float>
-    x - y };+  // On impose une variable. 
 +  // Elle peut être static / constexpr ou non. 
 +  // Il faut la déclarer comme une référence. 
 +  t.varr -> std::same_as<const float&>;
 }; };
 </code> </code>
  
 ====Application des concepts==== ====Application des concepts====
 +  * Vérification qu'une structure respecte un concept
 <code cpp> <code cpp>
-template <typename T, typename U+struct Rectangle 
-requires integral<T> && they_are_mathsy<T, U+
-void log(T&& x, y) +    consteval float area() const {return 1.;} 
-{ ... }+    consteval float mod(float f) {return f;} 
 +    static constexpr float varr = 2.f; 
 +}; 
 +static_assert(Shape<Rectangle>); 
 +</code> 
 + 
 +  * Forcer un template à respecter un concept 
 + 
 +<code cpp> 
 +template <class T> 
 +requires Shape<T> 
 +class AllFormes 
 +
 + 
 +}; 
 +</code> 
 + 
 +  * Cast d'un type vers un concept 
 + 
 +<code cpp> 
 +int main() 
 +
 +  Rectangle a; 
 +  Shape auto &b = a; 
 +  b.mod(); 
 +
 +</code> 
 + 
 +  * Déclaration d'une fonction dont un des paramètres doit respecter un concept 
 + 
 +<code cpp> 
 +void foo(const Concept auto&
 +{} 
 +</code> 
 + 
 +Et cela va générer un symbole pour chaque type. 
 + 
 +====Restriction==== 
 + 
 +===Fonction template=== 
 + 
 +Il n'est pas possible de définir un concept avec un template non défini dans le concept. 
 + 
 +Exemple: 
 + 
 +<code cpp> 
 +struct Goat { 
 +    template<class T> 
 +    void eat(T); 
 +}; 
 +</code> 
 + 
 +Il n'est pas possible de laisser ''eat'' template. Il faudra définir explicitement chaque surcharge. 
 + 
 +[[https://quuxplusone.github.io/blog/2020/08/10/concepts-cant-do-quantifiers/|Concepts can’t do quantifiers]] {{ :lang:cpp:concept:concepts_can_t_do_quantifiers_arthur_o_dwyer_stuff_mostly_about_c_2021-11-13_09_03_00_.html |Archive du 10/08/2020 le 13/11/2021}} 
 + 
 +====Migration C++17 vers C++20==== 
 + 
 +  * Code C++17 
 + 
 +<code cpp> 
 +#include <tuple> 
 + 
 +template <typename T> 
 +concept bool IShape = requires (T x, T z, int y) 
 +
 +   { T() } ; 
 +   { x = z } -> T&
 +   { T(x) }  ; 
 +   { x.countSides() } -> int; 
 +   { x.sideLength(y) } -> int; 
 +}; 
 + 
 +struct Rectangle 
 +
 +   Rectangle() {}; 
 +   Rectangle(const Rectangleother) {}; 
 +   Rectangle& operator=(Rectangle& other) {return *this; }; 
 + 
 +   const char * getName() { return "Rectangle";
 +   int countSides() {return 4;} 
 +   int sideLength(int side) { return (side % 2 == 0) ? 10 : 5; } 
 +}; 
 + 
 +struct Square 
 +
 +   Square() {}; 
 +   Square(const Square& other) {}; 
 +   Square& operator=(Square& other) {return *this; };   
 + 
 +   const char * getName() { return "Square";
 +   int countSides() {return 4;} 
 +   int sideLength(int side) { return 10; } 
 +}; 
 + 
 +void print(IShape& shape) 
 +
 +   for (int side = 0 ; side < shape.countSides() ; ++side ) 
 +   { 
 +      //std::cout << shape.getName() << " side=" << shape.sideLength(side) << "\n"; 
 +   } 
 +}; 
 + 
 +int main() 
 +
 +   Square square; 
 +   Rectangle rect; 
 +   auto shapes = std::make_tuple(square, rect); 
 +   std::apply([](auto&... shape) { ((print(shape)), ...); }, shapes) ; 
 + 
 +   return 0; 
 +}; 
 +</code> 
 + 
 +  * Code C++20 
 + 
 +<code cpp> 
 +#include <concepts> 
 +#include <tuple> 
 + 
 +template <typename T> 
 +concept IShape = requires (T x, T z, int y) 
 +{ 
 +   { T() } ; 
 +   { x = z } -> std::same_as<T&>; 
 +   { T(x) }  ; 
 +   { x.countSides() } -> std::same_as<int>; 
 +   { x.sideLength(y) } -> std::same_as<int>; 
 +}; 
 + 
 +struct Rectangle 
 +
 +   Rectangle() {}; 
 +   Rectangle(const Rectangle& other) {}; 
 +   Rectangle& operator=(Rectangle& other) {return *this; }; 
 + 
 +   const char * getName() { return "Rectangle";
 +   int countSides() {return 4;} 
 +   int sideLength(int side) { return (side % 2 == 0) ? 10 : 5; } 
 +}; 
 + 
 +struct Square 
 +
 +   Square() {}; 
 +   Square(const Square& other) {}; 
 +   Square& operator=(Square& other) {return *this; };   
 + 
 +   const char * getName() { return "Square";
 +   int countSides() {return 4;} 
 +   int sideLength(int side) { return 10; } 
 +}; 
 + 
 +void print(IShape auto& shape) 
 +
 +   for (int side = 0 ; side < shape.countSides() ; ++side ) 
 +   { 
 +      //std::cout << shape.getName() << " side=" << shape.sideLength(side) << "\n"; 
 +   } 
 +}; 
 + 
 +int main() 
 +
 +   Square square; 
 +   Rectangle rect; 
 +   auto shapes = std::make_tuple(square, rect); 
 +   std::apply([](auto&... shape) { ((print(shape)), ...); }, shapes) ; 
 + 
 +   return 0; 
 +};
 </code> </code>
lang/cpp/concept.1580936283.txt.gz · Dernière modification : de root