Fedor
Fedor

Reputation: 21271

Can concept checking be delayed till class instantiation in C++?

A common practice to speed up compilation is to only declare classes instead of giving their full definitions, e.g.

struct A;
template<typename T> struct B;
using C = B<A>;

By if one likes to use C++20 concepts in template classes then the code as follows

#include <concepts>
struct A;
template<std::destructible T> struct B;
using C = B<A>;

will result in error:

error: template constraint failure for 'template<class T>  requires  destructible<T> struct B'
     | using C = B<A>;

Is it possible to somehow delay the moment of concept checking till B<A> is really used/instantiated? If not, then it seems that concepts will significantly slow down compilation of some programs by forcing to include class definitions which were previously hidden.

Upvotes: 4

Views: 231

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275510

This is how you forward declare.

struct A;
template<class T> struct B;
using C = B<A>;

keep this. In B.h:

#include <concepts>
template<class T> struct B;
// or
template<class T> struct B
{
  static_assert( std::destructible<T> );
};

template<std::destructible T>
struct B<T> {
};

specialize. Leave the base B<T> undefined.

Now, the errors you get aren't going to be checked "early", but rather occur at a later spot. So passing T to B<> won't check in a SFINAE-friendly way.

But that basically is what you asked not to happen in your question.

Note that the static_assert may, under certain readings of the standard, make your program ill-formed, no diagnostic required. Basically all specializations (including the base one) must have a valid instantiation, and pattern matching of the other specialization makes this impossible.

But in practice I think you just get an error message.

Upvotes: 3

Related Questions