Home > Net >  constraints with c 20 concepts
constraints with c 20 concepts

Time:09-05

I'm trying to understand C 20 concepts, in particular the example from here. Why is it an error if we're templatizing f with a concept that's stricter than allowed? In other words doesn't Integral4 also satisfy the Integral concept?

#include <type_traits>
#include <concepts>

template<typename T>
concept Integral = std::integral<T>;

template<typename T>
concept Integral4 = Integral<T> && sizeof(T) == 4;

template<template<Integral T1> typename T>
void f(){
}

template<typename T>
struct S1{};

template<Integral T>
struct S2{};

template<Integral4 T>
struct S3{};

void test(){
    f<S1>();    // OK
    f<S2>();    // OK
    // error, S3 is constrained by Integral4 which is more constrained than
    // f()'s Integral
    f<S3>();
}

Error

<source>: In function 'void test()':
<source>:28:10: error: no matching function for call to 'f<template<class T>  requires  Integral4<T> struct S3>()'
   28 |     f<S3>();
      |     ~~~~~^~
<source>:11:6: note: candidate: 'template<template<class T1> class requires  Integral<T1> T> void f()'
   11 | void f(){
      |      ^
<source>:11:6: note:   template argument deduction/substitution failed:
<source>:28:10: error: constraint mismatch at argument 1 in template parameter list for 'template<template<class T1> class requires  Integral<T1> T> void f()'
   28 |     f<S3>();
      |     ~~~~~^~
<source>:28:10: note:   expected 'template<class T1> class requires  Integral<T1> T' but got 'template<class T>  requires  Integral4<T> struct S3'
Compiler returned: 1

CodePudding user response:

f takes a template template parameter that is constrained on Integral. This means that f is allowed to use any type T which satisfies Integral on this template.

For example, short.

S3 is a type constrained on Integral4, which subsumes Integral. This means that, while any type U which satisfies Integral4 will also satisfy Integral, the reverse is not true. There are some types T which satisfy Integral but not Integral4

short for example is Integral, but it is unlikely to satisfy Integral4.

But f has the right to use short on the template it is provided, because that's what its signature says it can do. Since S3 provided only allows a subset of the types that f's signature allows it to use, you get a compile error.

  • Related