https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91466

            Bug ID: 91466
           Summary: [concepts] indicates "used in its own initializer"
                    when not, constraint order change passes compilation.
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: frederik.engels24 at gmail dot com
  Target Milestone: ---

Run using "g++ (Compiler-Explorer-Build) 10.0.0 20190814 (experimental)" with
options "-std=c++2a -fconcepts"
and source code: https://godbolt.org/z/aGw2d0

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
#include <type_traits>
#include <array>

template<typename T>
concept integral_constant_ = std::is_empty_v<T> && std::is_trivial_v<T> &&
requires
{
    typename T::value_type;
    requires std::is_integral_v<typename T::value_type>;
    { T::value } -> typename T::value_type;
};

struct sz_fn
{
template<typename R> requires requires(R&& r) { {static_cast<R&&>(r).size()} ->
integral_constant_; }
constexpr auto operator()(R&& r) {
    return static_cast<R&&>(r).size();
}
};

constexpr auto sz = sz_fn{};


int main()
{
    auto arr = std::array<int, 5>{1, 2, 3, 4, 5};

    return !std::is_invocable_v<decltype(sz), decltype(arr)>;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

results in:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from <source>:1:

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits: In
substitution of 'template<class _Fn, class ... _Args> static
std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)),
std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn =
const sz_fn; _Args = {std::array<int, 5>}]':

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:2563:55:
  required from 'struct std::__result_of_impl<false, false, const sz_fn,
std::array<int, 5> >'

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:2976:12:
  recursively required by substitution of 'template<class _Result, class _Ret>
struct std::__is_invocable_impl<_Result, _Ret, std::__void_t<typename
_CTp::type> > [with _Result = std::__invoke_result<const sz_fn, std::array<int,
5> >; _Ret = void]'

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:2976:12:
  required from 'struct std::is_invocable<const sz_fn, std::array<int, 5> >'

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:3021:27:
  required from 'constexpr const bool std::is_invocable_v<const sz_fn,
std::array<int, 5> >'

<source>:28:18:   required from here

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:2552:26:
error: the value of 'std::is_empty_v<integral_constant_>' is not usable in a
constant expression

 2552 |       std::declval<_Fn>()(std::declval<_Args>()...)

      |       ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:3103:25:
note: 'std::is_empty_v<integral_constant_>' used in its own initializer

 3103 |   inline constexpr bool is_empty_v = is_empty<_Tp>::value;

      |                         ^~~~~~~~~~

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:2552:26:
error: the value of 'std::is_trivial_v<integral_constant_>' is not usable in a
constant expression

 2552 |       std::declval<_Fn>()(std::declval<_Args>()...)

      |       ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~

/opt/compiler-explorer/gcc-trunk-20190815/include/c++/10.0.0/type_traits:3092:25:
note: 'std::is_trivial_v<integral_constant_>' used in its own initializer

 3092 |   inline constexpr bool is_trivial_v = is_trivial<_Tp>::value;

      |                         ^~~~~~~~~~~~

Compiler returned: 1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Changing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<typename T>
concept integral_constant_ = std::is_empty_v<T> && std::is_trivial_v<T> &&
requires
{
    typename T::value_type;
    requires std::is_integral_v<typename T::value_type>;
    { T::value } -> typename T::value_type;
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
to
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<typename T>
concept integral_constant_ =
requires
{
    typename T::value_type;
    requires std::is_integral_v<typename T::value_type>;
    { T::value } -> typename T::value_type;
} && std::is_empty_v<T> && std::is_trivial_v<T>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Allows the program to compile successfully.

Reply via email to