I have this code where if you comment out the line commented "But this doesn't work?!" it compiles just fine, but if you don't, the compiler generates an error.
At least, gcc 8.2 generates an error.
But, they seem identical to me. What's the problem? Is this legal code at all?
template <int x>
struct test_template {
static int size() { return x; }
};
constexpr int ce_strlen(char const *s)
{
int i = 0;
while (s[i]) ++i;
return i;
}
int joe()
{
constexpr int plen = ce_strlen(__PRETTY_FUNCTION__); // This works
test_template<plen> a; // This declaration is valid.
test_template<ce_strlen(__PRETTY_FUNCTION__)> b; // But this doesn't work?!
return a.size() + b.size();
}
I ran into this while trying to come up with a way to create profile tags for an intrusive profiling system at compile time. I succeeded, but my final code does not involve using ce_strlen
.
The identifier __PRETTY_FUNCTION__ holds the name of the function pretty printed in a language specific fashion. These names are always the same in a C function, but in a C++ function they may be different. For example, this program: extern "C" { extern int printf (char *, ...
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
The easiest way to check whether a function (e.g., foo ) is constexpr is to assign its return value to a constexpr as below: constexpr auto i = foo(); if the returned value is not constexpr compilation will fail.
Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.
Indeed this is a bug in GCC as discussed in the comments, but I thought I'd throw in some additional insight as to the nature of this bug. In the GCC NEWS file there is this line:
__FUNCTION__
and__PRETTY_FUNCTION__
are now treated as variables by the parser; previously they were treated as string constants. So code likeprintf (__FUNCTION__ ": foo")
must be rewritten toprintf ("%s: foo", __FUNCTION__)
. This is necessary for templates.
But __PRETTY_FUNCTION__
isn't really a variable, it's a special case treated in the parser as we see in constexpr.c
:
case DECL_EXPR:
{
tree decl = DECL_EXPR_DECL (body);
if (TREE_CODE (decl) == USING_DECL
/* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */
|| DECL_ARTIFICIAL (decl))
return NULL_TREE;
return error_mark_node;
}
If it really was a variable, we'd expect it to pass the same test cases as these:
constexpr const char* s2 = "TEST";
constexpr const char* s3 = s2;
test_template<ce_strlen("TEST")> c;
test_template<ce_strlen(s2)> d;
test_template<ce_strlen(s3)> e;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With