0

In the following code I try to constexpr construct a data structure and then use one of the constexpr initialized members (a_) in a method to branch with if constexpr().

From a logical standpoint AFAIK nothing speaks against it: Of course, the memory location is only known at runtime, the this-pointer passed to the method therefore will only be known at runtime. However, constexpr branch elision can be done before, when the constexpr data is written into the binary, the compiler could take another turn and constexpr elide one of the branches because a_ is known for every struct. Of course this would mean that the compiler generates instructions for multiple methods, one for each branch.

Am I making a mistaken or are compilers lacking behind in this departement?

(Erroneous) Demo

#include <array>
#include <initializer_list>
#include <cstdio>
#include <algorithm>

struct channel
{
    constexpr channel(int a)
        :   a_{a}
    {}
    
    constexpr void compile_time_decide() const {
        if constexpr (a_ > 5) {
            printf("Decided at compile time!\n");
        } else {
            printf("Decided at compile time!\n");
        }
    }

    const int a_;
};

template <size_t N>
struct light_service
{
    constexpr light_service(std::array<channel, N> channels)
        :   channels_{channels}
    { }

    void runtime_invoke() {
        std::for_each(channels_.begin(), channels_.end(), [](channel& ch){ ch.compile_time_decide(); });
    }

    std::array<channel, N> channels_;
};

constinit light_service<10> light{{1,2,3,4,5,6,7,8,9,10}};

int main()
{
    light.runtime_invoke();
}
glades
  • 3,778
  • 1
  • 12
  • 34
  • `a_` is not a constant expression so you cannot use it in condition for `constexpr if`. – Jason Sep 07 '22 at 15:34
  • @JasonLiam but a_ is known at compile time – glades Sep 07 '22 at 15:35
  • 1
    No it is not known at compile time. I have a dupe for this. See [Why are only some consts useable in compile time array sizes?](https://stackoverflow.com/questions/72597798/why-are-only-some-consts-useable-in-compile-time-array-sizes/72597941#72597941) – Jason Sep 07 '22 at 15:36
  • @JasonLiam I think you're missunderstanding me. If you exclude the method body you can see that the struct light is written in the instruction binary as-is and every constant from 1-10 is present. This is what constinit does. – glades Sep 07 '22 at 15:45
  • 1
    I am sure that `a_` is not a constant expression and so you cannot use it as one. – Jason Sep 07 '22 at 15:47
  • @glades `consinit` guarantees that the variable has static/constant initialization. It does not make something `const` nor does it make something a constant expressions. To use something at compile time, it must be a compile time constant and `constinit` doesn't give you that. https://en.cppreference.com/w/cpp/language/constinit – NathanOliver Sep 07 '22 at 15:49
  • @NathanOliver Ok I guess my mistake was in assuming that a compile time constant implies it's a constant expression. It also doesn't work however if I make light a constexpr. Where exactly lies the difference? I thought that once the const shows up in the binary as a fixed value the compiler could use it to make other compile time assumptions (like constexpr) – glades Sep 07 '22 at 15:53
  • @glades: `const` is not something you should think of as propagating up the chain of ownership. If a struct has only one member that is declared `const`, that doesn't make uses of the struct `const`, let alone a constant expression. Always be clear about how you mean to use the thing you're writing. If you want `light` to be usable in a constant expression, then declare it `constexpr`. – Nicol Bolas Sep 07 '22 at 16:18
  • @NicolBolas Thank you, I kind of meant the reverse: Having the struct constexpr must initialize all members at compile time. So it's more of a propagation downwards. The a_ is not constexpr, however the containing struct can be constexpr which will instantiate the variable a_ into the binary. This is why I was wondering if it was possible to compile-time check this manifested value with if constexpr() – glades Sep 07 '22 at 18:55

0 Answers0