c++language-lawyerc++20c++-conceptsincomplete-type

What is expected concept evaluation result for an incomplete type?


If I have an incomplete type, and evaluate some concept for it, for example some concept from the standard library:

#include <concepts>

int main() {
    struct S;
    return std::destructible<S>;
}

What result must be produced here by the program?

On practice I see that EDG returns 1 here. GCC and MSVC both return 0. And Clang with libc++ fails the compilation:

/opt/compiler-explorer/clang-20.1.0/bin/../include/c++/v1/__type_traits/is_nothrow_destructible.h:28:31: error: incomplete type 'S' used in type trait expression
   28 |     : integral_constant<bool, __is_nothrow_destructible(_Tp)> {};
      |                               ^

Online demo: https://gcc.godbolt.org/z/9as4jKM1q

Which implementation is correct?


Solution

  • TL;DR: it's undefined behavior.


    The definition of std::destructible is ([concept.destructible]):

    template<class T>
    concept destructible = is_nothrow_destructible_v<T>;
    

    The definition of is_nothrow_destructible_v is ([meta.type.synop]):

    template<class T>
    constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<T>::value;
    

    And is_nothrow_destructible requires that ([meta.unary.prop]):

    T shall be a complete type, cv void, or an array of unknown bound.

    So in order to determine the value of std::destructible<S>, we need to evaluate is_nothrow_destructible_v<S>, which is defined in terms of is_nothrow_destructible<S>::value, which requires S to be a complete type. Since S is an incomplete type, the precondition is violated, and thus the behavior is undefined.