在以下示例中,我使用foo
来验证在编译时确定static_assert
。 foo
通过,我检查的条件不正确,它实际上是活动的。这意味着skip_first_word
在编译时是已知的。但是,如果我使用调试器逐步执行代码,我会看到// Skip the first word in p_str
constexpr const char * skip_first_word(const char * p_str) {
return (*p_str == '\0') ? p_str :
(*p_str == ' ') ? p_str + 1 :
skip_first_word(p_str + 1);
}
// constexpr to calculate the length of a string
constexpr size_t str_len(const char * p_str) {
return (*p_str == '\0') ? 0 : str_len(p_str + 1) + 1;
}
int main()
{
constexpr auto foo = skip_first_word("Hello, World!");
constexpr auto foo_size = str_len(foo);
static_assert(foo_size == 6, "Wrong size");
// This assert successfully fails
// static_assert(foo_size == 7, "Wrong size");
// Prevent optimizations
for(auto ptr = foo; *ptr != '\0'; ++ptr) {
volatile auto sink = ptr;
}
volatile auto sink = &foo_size;
return 0;
}
也在运行时执行。
foo
这里发生了什么?为什么在编译时计算的myAPIService.postUploadImage = function (formdata) {
var request = {
url: urlBase + 'UploadImage',
method: 'POST',
data: formdata,
headers: {
'Content-Type': undefined
}
}
return $http(request);
};
不能在运行时使用?
编辑:Visual Studio 2015中会出现此行为
答案 0 :(得分:5)
gcc.godbolt.org使用-std=c++11 -O1
标记显示您的代码已使用 gcc 7 和 clang 3.9 完全优化。
取消注释volatile
操作显然会生成汇编指令,但不会为skip_first_word
或str_len
生成任何说明。
您对Visual Studio的判断是正确的:使用CL 19 on gcc.beta.godbolt.org显示正在为以下内容生成程序集:
constexpr auto foo = skip_first_word("Hello, World!");
constexpr auto foo_size = str_len(foo);
这看起来像编译器实现缺陷,因为constexpr
变量应该并且可以在编译时完全计算。此外,变量正在static_assert
中使用,保证在编译时评估。这似乎表明编译器不必要地为skip_first_word
和str_len
生成程序集,即使它们从未在运行时上下文中使用。
手动内联代码如下......
static_assert(str_len(skip_first_word("Hello, World!")) == 6, "Wrong size");
static_assert(str_len(skip_first_word("Hello, World!")) != 7, "Wrong size");