I am currently trying to find a clean way to create a templated bytearray structure that can be initialized differently based on whether its constructor was instantiated with or without the constexpr keyword, And I also want to apply it to other methods and function if possible, I wonder if there is a way to achieve this?
Here is an example of what I want to achieve:
#include <iostream>
#include <cstring>
template<size_t N>
struct bytearray {
char data[N];
constexpr bytearray(char val) : data() {
if constexpr (... is compile time instantiated ...) {
for (size_t i = 0; i < N; ++i) {
data[i] = val;
}
} else {
std::memset(data, val, N);
}
}
};
int main() {
constexpr bytearray<10> A(7);
bytearray<10> B(7);
}
So instantiating the A
class at compile time will use the for
loop, then memcpy
if it was not.
You are looking for if consteval
:
constexpr bytearray(char val) : data() {
if consteval {
for (size_t i = 0; i < N; ++i) {
data[i] = val;
}
} else {
std::memset(data, val, N);
}
}
This is a C++23 feature. In C++20, you can use std::is_constant_evaluated
:
constexpr bytearray(char val) : data() {
if (std::is_constant_evaluated()) {
for (char& byte : data) {
byte = val;
}
} else {
std::memset(data, val, N);
}
}
Though note in this specific case, the check isn't necessary. for (size_t i = 0; i < N; ++i) data[i] = val;
will be compiled to the same thing as a memset
on any compiler worth its salt.