I'm writing a constexpr
code and I would like to inspect computed values at compile time.
The usual trick is to do something like this:
struct ReturnValue
{
int value1;
int value2;
};
constexpr ReturnValue doTheComputation()
{
return { .value1 = 10, .value2 = 20 };
}
template< auto t > struct p;
p< doTheComputation() > foo;
This gives a nice compile error:
implicit instantiation of undefined template 'p<ReturnValue{10, 20}>'
and I can see the value of the result.
However, this does not work for non-structural types, like std::string_view
, std::string
, or anything that resembles a string, as such types are not allowed to be NTTP.
Non-working example with std::string_view
: https://godbolt.org/z/da8W557nK
Non-working example with char const *
: https://godbolt.org/z/5Mvqfx95q
Even if I use char const[ some_large_numer ]
to ensure the message fits, like this, instead of a string, I get the ASCII values listed as template parameters:
implicit instantiation of undefined template 'p<ReturnValue{{115, 111, 109, 101, 32, 115, 101, 99, 114, 101, ...}}>
Are there any tips or tricks to print values of non-structural types at compile-time (as results of constexpr functions)?
I've seen an unofficial patch for GCC that apparently solves that (I haven't tested it), but I'm searching for a solution for clang (Apple-clang from Xcode 15 or newer and LLVM 18 or newer).
Inspired by the idea by @WeijunZhou from comments to the question, I searched more. I discovered that C++26 has a flavor of static_assert
that allows the second parameter to be a string-like result of constexpr
computation (C++ reference).
Unfortunately, std::format
is not constexpr
-friendly even in C++26 (cpp-reference confirms this), but I can always write my formatting function that outputs string-like literal object (according to the specification, it only needs to provide .size()
and .data()
functions), so I came up with the following solution:
#include <string_view>
#include <string>
struct ReturnValue
{
std::string_view data;
std::string data2;
};
constexpr ReturnValue doTheComputation()
{
return { .data = "some secret message", .data2 = "owned data" };
}
constexpr std::string format( ReturnValue const & val )
{
std::string result{ val.data };
result += ", additional data: ";
result += val.data2;
return result;
}
static_assert( false, format( doTheComputation() ) );
This appears to work on LLVM 18, but not yet on Apple-Clang shipped with Xcode 15.4 (I still need to test with Xcode 16 beta).
In general, it's a workable solution, but I would still be happier if somebody came up with a solution that I could use on Xcode 15.4.