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.