I am using clangd as LSP, with C++20 and I have stuck with such a problem. I have no idea why I cannot initialize a constexpr array with a constexpr function. Inserting a direct values works but I would like to understand why my "automatic" solution doesn't work.
Error returned by clangd LSP is probably because of a second issue, but I don't know why defined function is not seen as defined.
IpRange.h
class IpRange {
inline static constexpr uint32_t getMaskValue(const ushort shortForm) {
return 2^(32 - shortForm) - 1;
}
template <typename T>
inline static constexpr T getMaskValues() {
auto masks = T();
for (ushort i = 0; i < 33 ; i++) {
masks[i] = getMaskValue(i);
}
return masks;
}
static constexpr std::array<uint32_t, 33> maskValues { getMaskValues<std::array<uint32_t, 33>>() };
//Returns clangd error: Constexpr variable 'maskValues' must be initialized by a constant expression
//Returns compilation error: constexpr T IpRange::getMaskValues() [with T = std::array<unsigned int, 33>]’ used before its definition
static constexpr std::array<uint32_t, 33> maskValues { 1, 2, 3 };
//Works fine...
}
Solution. Moving Masks-stuff to another class.
#define MASK_VAL_NUM 33
class MaskValues {
typedef std::array<uint32_t, MASK_VAL_NUM> MaskValA;
inline static constexpr uint32_t getMaskValue(const ushort shortForm) {
return 2^(32 - shortForm) - 1;
}
inline static constexpr MaskValA getMaskValues() {
auto masks = MaskValA();
for (ushort i = 0; i < MASK_VAL_NUM ; i++) {
masks[i] = getMaskValue(i);
}
return masks;
}
const std::array<uint32_t, MASK_VAL_NUM> maskValues;
public:
constexpr MaskValues(): maskValues{getMaskValues()} {
}
const uint32_t& operator[](std::size_t idx) const {
return this->maskValues[idx];
}
};
class IpRange {
static constexpr MaskValues maskValues {};
}
return 2^(32 - shortForm) - 1;looks like a mistake.^is bitwise xor; it is not exponentiation.