I need to create an array of static data, where the size (and data) is known at compile time, but differs between build configurations.
This is a very dumbed-down version of what I'm trying to do (Please ignore glaring bad practices in this code as it is just an example):
constexpr ProductType PRODUCT = ProductType::A;
constexpr size_t dataSize() { return PRODUCT == ProductType::A ? 3 : 4; }
constexpr std::array<int, dataSize()> createArray()
{
if constexpr (dataSize() == 4) {
return std::array<int, dataSize()>{1, 2, 3, 4};
} else {
return std::array<int, dataSize()>{1, 2, 3};
}
}
But this code fails to compile. The first branch of the constexpr-if
is still evaluated and deemed invalid:
<source>:22:54: error: too many initializers for 'std::array<int, 3>'
22 | return std::array<int, dataSize()>{1, 2, 3, 4};
| ^
But reading the docs I was under the impression that the code in the non-active branch of constexpr-if
can contain code that will return wrong type, so why wouldn't this work?
The condition you pass to if constexpr
does not depend on any template parameters, so both branches are compiled.
Outside a template, a discarded statement is fully checked.
if constexpr
is not a substitute for the#if
preprocessing directivevoid f() { if constexpr(false) { int i = 0; int *p = i; // Error even though in discarded statement } }