[Bug c++/86282] Evaluation order in if constexpr expression seems to be irrelevant for evaluating type traits
redi at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Jun 22 13:54:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86282
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |RESOLVED
Resolution|--- |INVALID
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I think GCC's behaviour is correct, as required by the standard.
Firstly, if constexpr in main() doesn't work the way you want, because there's
nothing dependent (there is no possible version of the function where the
condition will be true, so the program is ill-formed).
Secondly, if constexpr doesn't short-circuit the instantation of templates and
concepts used in the condition, so the entire thing is instantiated even if the
actual boolean evaluation short-circuits.
That can be solved by using two nested ifs:
if constexpr (has_begin<decltype(p)>)
if constexpr (has_begin<...>)
Or using std::conjunction, which does avoid instantiating anything that isn't
needed (but would require changing your code to use with that concept):
https://en.cppreference.com/w/cpp/types/conjunction
Here's a working version:
#include <utility>
#include <type_traits>
#include <vector>
template <typename type>
concept bool has_begin = requires (type v)
{
{ std::begin(v) }
};
template<typename T>
int f(T p)
{
if constexpr (has_begin<T>)
if constexpr
(has_begin<std::remove_reference_t<decltype(*std::begin(p))>>)
return 0;
return 1;
}
int main()
{
f(1);
f(std::vector<std::vector<int>>{});
f(std::vector<int>{});
}
More information about the Gcc-bugs
mailing list