我有这段代码,如果您在注释为“ 但这行不通?!”的行中注释掉,它可以正常编译,但是如果不这样做,则编译器会生成错误。
但是,它们似乎与我相同。有什么问题?这是法律法规吗?
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();
}
我在尝试提出a way to create profile tags for an intrusive profiling system at compile time时遇到了这个问题。我成功了,但是我的最终代码不涉及使用ce_strlen
。
答案 0 :(得分:15)
实际上,正如评论中所讨论的,这是GCC中的一个错误,但是我认为我对该错误的性质有一些其他的见解。在海湾合作委员会NEWS file中,有以下这一行:
现在,解析器将
__FUNCTION__
和__PRETTY_FUNCTION__
视为变量;以前,它们被视为字符串常量。因此,必须将printf (__FUNCTION__ ": foo")
之类的代码重写为printf ("%s: foo", __FUNCTION__)
。这对于模板是必需的。
但是__PRETTY_FUNCTION__
并不是一个真正的变量,它是解析器中处理的一种特殊情况,正如我们在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;
}
如果它确实是一个变量,我们希望它通过与以下相同的测试用例:
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;