NFC: Concepts and fixed-pointing interact poorly

Fortunately, C++ taketh away and C++ giveth, both, so here we are: a way to
detect if we're in the middle of definining a type that uses itself as a
template parameter in a way that flows into a concept check and, if so,
short-circuit out of the need to actually do any checks.  Wonders never cease.
This commit is contained in:
Nathaniel Wesley Filardo
2021-08-23 21:24:16 +01:00
committed by Nathaniel Wesley Filardo
parent f913f8b820
commit 3c14a7ddf1

View File

@@ -38,5 +38,34 @@ namespace snmalloc
template<typename T, typename U>
concept ConceptSame = std::is_same<T, U>::value;
# endif
/**
* Some of the types in snmalloc are circular in their definition and use
* templating as a lazy language to carefully tie knots and only pull on the
* whole mess once it's assembled. Unfortunately, concepts amount to eagerly
* demanding the result of the computation. If concepts come into play during
* the circular definition, they may see an incomplete type and so fail (with
* "incomplete type ... used in type trait expression" or similar). However,
* it turns out that SFINAE gives us a way to detect whether a template
* parameter refers to an incomplete type, and short circuit evaluation means
* we can bail on concept checking if we find ourselves in this situation.
*
* See https://devblogs.microsoft.com/oldnewthing/20190710-00/?p=102678
*
* Unfortunately, C++20 concepts are not first-order things and, in
* particular, cannot themselves be template parameters. So while we would
* love to write a generic Lazy combinator,
*
* template<template<typename> concept C, typename T>
* concept Lazy = !is_type_complete_v<T> || C<T>();
*
* this will instead have to be inlined at every definition (and referred to
* explicitly at call sites) until C++23 or later.
*/
template<typename, typename = void>
constexpr bool is_type_complete_v = false;
template<typename T>
constexpr bool is_type_complete_v<T, std::void_t<decltype(sizeof(T))>> = true;
} // namespace snmalloc
#endif