Would be possible to iterate over a constexpr
C-array/std::array
/vector
and execute constexpr
operations on each element and everything to be done at compile time?
https://godbolt.org/z/5a4v3Eerh
#include <string_view>
using namespace std::string_view_literals;
constexpr std::string_view arr[] = {"ab"sv, "xyz"sv,};
int main(){
static_assert(arr[0] == "ab"); //OK
static_assert(arr[1] == "xyz");
#if 0 //would something like this be possible?
for(const auto i: arr){
static_assert(i == "xyz"); //???
}
#endif
return 0;
}
I used static_assert()
but there could be any constexpr
function ...
Any suggestion would be appreciated! any C++ standard (preferably the latest), any compiler (preferably Microsoft VisualStudio 2022)
After reading all your suggestions, my conclusions are:
std::array<std:string_view>
because it is constexpr
-friendly and the operator==()
can be used to compare 2 objects of this type:constexpr std::array<std::string_view,2> inp = {/*...*/};
constexpr std::array<std::string_view,2> out = someConstexprFunc(inp);
constexpr std::array<std::string_view,2> ref = {/*...*/};
static_assert(out == ref);
It is simpler but doesn't provide information about the index causing an eventual mismatch
operator==()
with a constexpr
function returning the index and use that index as template parameter for an error class with a meaningful name:#include <algorithm>
#include <array>
#include <ranges>
#include <string_view>
using namespace std::string_view_literals;
consteval auto run(std::ranges::range auto const& range){
std::remove_cvref_t<decltype(range)> res;
std::transform(range.cbegin(), range.cend(), res.begin(), [](const std::string_view s){
return s.substr(0, 1);
});
return res;
}
template<size_t N>
constexpr size_t cmp(const std::array<std::string_view,N>&a, const std::array<std::string_view,N>&b){
for(size_t i=0; i<N; ++i){
if(a[i] != b[i]){
return i+1;
}
}
return 0;
}
template<size_t index> struct CompareErrorAtIndex{
static_assert(index == 0, "compare `out` with `ref`");
};
constexpr std::array<std::string_view,2> inp = {"ab"sv, "xyz"sv};
constexpr std::array<std::string_view,2> out = run(inp);
constexpr std::array<std::string_view,2> ref = {"a"sv, "x"sv,};
int main(){
//static_assert(out == ref); //OK but no info about index generating the error
constexpr auto index = cmp(out, ref);
if constexpr(index){
CompareErrorAtIndex<index>();
}
return index;
}
The error class together with its template argument (the index) will appear in the build output for all 3 main compilers (msvc, clang, gcc) like, for example: ... CompareErrorAtIndex<1> ...
You can see it in action at https://godbolt.org/z/z41TqhvPE
Thank you very much for your input! (I'm still open for comments, suggestions, improvements, constructive critics)