C++20 Template Template Concept Syntax

Viewed 661

With concepts, C++20 provides nice syntax like

template<typename T>
concept SomeConcept = true; // stuff here


template<typename T>
requires SomeConcept<T>
class Foo;

template<SomeConcept T>
class Foo;

where the two ways of concept restricting the class are equivalent, but the latter is just more concise.

If i now have some template template concept like

template<template<typename> typename T>
concept SomeOtherConcept = true; // stuff here

template<template<typename> typename T>
requires SomeOtherConcept<T>
class Foo;

i do not know the non-verbose (concise / short) syntax for this without an requirement clause, as things like

template<template<typename> SomeotherConcept T>
class Foo;

template<template<SomeOtherConcept> typename T>
class Foo;

did not work, so

What is the correct syntax for declaring such a template template class with a concept restriction to the template template parameter?

2 Answers

What is the correct syntax for declaring such a template template class with a concept restriction to the template template parameter?

The only way to write a constraint that depends on a template template parameter or a non-type template parameter is with a requires-clause. The shorter type-constraint syntax is only available for concepts that constrain types (hence the name type-constraint):

template <typename T> concept Type = true;
template <template <typename...> class Z> concept Template = true;
template <auto V> concept Value = true;

// requires-clause always works
template <typename T> requires Type<T> struct A { };
template <template <typename...> class Z> requires Template<Z> struct B { };
template <auto V> requires Value<V> struct C { };

// type-constraint only for type concepts
template <Type T> struct D { };

// abbreviated function template definitely only for type concepts
void e(Type auto x);

This is a trick that I have used before.

Define a lambda in the primary expression using a noop-like function as shown:

void noop(auto) {}

//...

template<typename T>
concept SomeConcept = true;

/*
template <template<typename>SomeConcept T>
struct Example {};
*/ //does not work

template <template<typename>typename T>
  requires requires() {
    {
      noop(
        []<typename TArg> requires SomeConcept<typename T<TArg>> (){}
      )
    };
  }
struct Example {};
Related