4

From the description on cppreference.com, I was under the impression that std::disjunction is designed to give me short-circuiting at compile-time, so that I can use it like this:

#include <type_traits>
#include <iostream>

template<nullptr_t null = nullptr>
constexpr bool does_not_compile() {
    static_assert(null != nullptr);
    return false;
}

void hello_world () {
    if constexpr (std::disjunction_v<std::true_type, std::bool_constant<does_not_compile()>>) {
        std::cout << "Hello World!" << std::endl;
    }
}

However, this does not compile, std::disjunction does not short-circuit in the sense that the above static_assert doesn't trigger (live example).

But then it what sense is it short-circuiting? It can't be the usual behavior of || at run time, because the type of the std::disjunction has to be known at compile time, and it depends on its value.

x432ph
  • 400
  • 1
  • 10
  • Now by experimenting a bit more with static_assert and if constexpr, I observe very strange interactions between them. For example, an unreachable static_assert(false) produces an compilation error, but reformulating in a way so that the compiler doesn't know that it is false in every instantiation, then it compiles just fine. – x432ph Apr 01 '19 at 21:52

1 Answers1

6

You find an explanation right on the page you linked to:

Disjunction is short-circuiting: if there is a template type argument Bi with bool(Bi::value) != false, then instantiating disjunction<B1, ..., BN>::value does not require the instantiation of Bj::value for j > i

The short-circuiting behavior concerns the value member of each parameter type, not the parameter type itself. You cannot instantiate a template without knowing it's paramters. And using std::disjunction<…> will generally require an instantiation. In your example

std::disjunction_v<std::true_type, std::bool_constant<does_not_compile()>>

the compiler still has to instantiate std::bool_constant<does_not_compile()> so that it knows what the whole std::disjunction<…> comes out to be (as you have noted yourself). What is guaranteed is that it won't instantiate std::bool_constant<does_not_compile()>::value

Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39
  • Ah, I think I understand. I made another live demo to observe this: http://coliru.stacked-crooked.com/a/21b0f0cabb007b03 This compiles, and if you change std::true_type to std::false_type, then the static_assert triggers. – x432ph Apr 01 '19 at 21:24
  • @x432ph yep, that's exactly it. – Michael Kenzel Apr 01 '19 at 21:24