c++c++20c++-conceptsrequires-expression

How to define a concept that requires T to have a T::inner member


I am learning the newly implemented concepts of C++20 standard using g++ 10. I am stuck with a simple type requirement. Namely I want to implement a requirement for a template argument T to have T::inner member name. Here is my code with error. What is wrong with this simple code and how to fix it?

#include<concepts>

template<typename T>
concept ContainsInner = requires
{
  typename T::inner;
};

template<ContainsInner T>
struct S{};

struct Q
{
  int inner;
};

int main()
{
  S<Q> s;     // instantiate S with Q for template type, 
              // which must satisfy the ContainsInner concept.
              // Q indeed contains the inner name but still the compilation fails
}

Solution

  • This:

    template<typename T>
    concept ContainsInner = requires
    {
      typename T::inner;
    };
    

    is requiring that T has a type named inner. Which gcc tells you in its error:

    source>:6:12: note: the required type 'typename T::inner' is invalid
        6 |   typename T::inner;
          |   ~~~~~~~~~^~~~~~~~~
    

    Q doesn't have a type named inner. If what you want is to have a member variable named inner, then you want:

    template<typename T>
    concept ContainsInner = requires(T t) {
        t.inner;
    };
    

    Note that this doesn't even check what type it is, just that it exists. Which isn't very useful. Maybe you want to require that it's an int:

    template<typename T>
    concept ContainsInner = requires(T t) {
        { t.inner } -> std::same_as<int&>;
    };