[Bug c++/86282] Evaluation order in if constexpr expression seems to be irrelevant for evaluating type traits

2018-06-22 Thread rene.r...@fu-berlin.de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86282

--- Comment #5 from rene.r...@fu-berlin.de ---
Many thanks for the explanation and the code examples.

[Bug c++/86282] Evaluation order in if constexpr expression seems to be irrelevant for evaluating type traits

2018-06-22 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86282

--- Comment #4 from Jonathan Wakely  ---
(In reply to rene.rahn from comment #2)
> thanks for enlighten me. Before, it wasn't clear to me, that if the nested
> version works, the conjunction does not necessarily.

The magic "does not get instantiated when false" feature of if-constexpr only
applies to the body of the else branch, not to the actual condition being
tested.

When you have a nested constexpr-if the some_fn(t) expression only occurs
inside the body, where it's valid. If it occurs in the condition, it still gets
instantiated.

[Bug c++/86282] Evaluation order in if constexpr expression seems to be irrelevant for evaluating type traits

2018-06-22 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86282

--- Comment #3 from Jonathan Wakely  ---
Using std::conjunction:

template
  using has_begin2 = std::bool_constant>;

template
  struct has_nested_begin
  {
// ill-formed unless has_begin is true:
static constexpr bool value =
has_begin()))>>;
  };

template
int f(T)
{
if (std::conjunction_v, has_nested_begin>)
  return 0;
return 1;
}

When has_begin2::value is false, has_nested_begin::value is not needed,
so is not instantiated.

[Bug c++/86282] Evaluation order in if constexpr expression seems to be irrelevant for evaluating type traits

2018-06-22 Thread rene.r...@fu-berlin.de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86282

--- Comment #2 from rene.r...@fu-berlin.de ---
Hi Jonathan,

thanks for enlighten me. Before, it wasn't clear to me, that if the nested
version works, the conjunction does not necessarily.

[Bug c++/86282] Evaluation order in if constexpr expression seems to be irrelevant for evaluating type traits

2018-06-22 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86282

Jonathan Wakely  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |INVALID

--- Comment #1 from Jonathan Wakely  ---
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)
  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 
#include 
#include 

template 
concept bool has_begin = requires (type v)
{
{ std::begin(v) }
};

template
int f(T p)
{
if constexpr (has_begin)
  if constexpr
(has_begin>)
return 0;
return 1;
}

int main()
{
  f(1);
  f(std::vector>{});
  f(std::vector{});
}