当无法在编译时评估 constexpr 时,gcc 中有一种方法可以得到警告吗?
There is a way in gcc to get a warning when a constexpr can't be evaluated at compile time?
我正在使用 gcc 5.1.0 (c++14) 并尝试使用 constexpr。验证我实现的 constexpr 是否在编译时进行评估非常烦人。我找不到任何标志来获得关于这种情况的警告。
这是一个例子:
example.cpp----------------------------------------
#include <stdlib.h>
const char pruVar[] = "12345678901234567";
[[gnu::noinline]] constexpr unsigned int myStrlen(const char* cstr)
{
unsigned int i=0;
for(;cstr[i]!=0;++i);
return i;
}
struct CEXAMPLE
{
unsigned int size;
constexpr CEXAMPLE(const char* s): size(myStrlen(s))
{
}
};
int main(void)
{
CEXAMPLE c(pruVar);
unsigned int size = myStrlen(pruVar);
void* a = malloc(c.size + size);
if (a != nullptr)
return 0;
else
return 1;
}
在示例中 CEXAMPLE::CEXAMPLE 在编译时求值,包括其中对 myStrlen 的调用,但在 main 中对 myStrlen 的调用在运行时求值。我必须知道的唯一方法是查看 assembler.This 网站也非常有用:http://gcc.godbolt.org/
如果您知道如何让编译器对此或类似的事情发出警告,我将不胜感激
myStrlen(pruVar)
可以在编译时求值;在这种情况下,编译器只是选择不这样做。
如果你想强制编译器在编译时评估它,或者如果这是不可能的错误,请将结果分配给 constexpr
变量:
constexpr unsigned int size = myStrlen(pruVar);
^^^^^^^^^
您也可以使用 enum
或 std::integral_constant
:
enum : unsigned int { size = myStrlen(pruVar) };
std::integral_constant<unsigned int, myStrlen(pruVar)> size;
基于必须在编译时评估模板参数这一事实,可以使用辅助模板。
namespace helper {
template<class T, T v> constexpr T enforce_compiletime() {
constexpr T cv = v;
return cv;
}
}
#define compiletime(arg) ::helper::enforce_compiletime<decltype(arg), (arg)>()
这允许在没有额外的 constexpr 变量的情况下执行编译时,这对于计算值查找表很方便。
constexpr uint32_t bla(uint8_t blub) {
switch (blub) {
case 5:
return 22;
default:
return 23;
}
}
struct SomeStruct {
uint32_t a;
uint32_t b;
};
SomeStruct aStruct = {compiletime(bla(5)), compiletime(bla(6))};
我正在使用 gcc 5.1.0 (c++14) 并尝试使用 constexpr。验证我实现的 constexpr 是否在编译时进行评估非常烦人。我找不到任何标志来获得关于这种情况的警告。
这是一个例子: example.cpp----------------------------------------
#include <stdlib.h>
const char pruVar[] = "12345678901234567";
[[gnu::noinline]] constexpr unsigned int myStrlen(const char* cstr)
{
unsigned int i=0;
for(;cstr[i]!=0;++i);
return i;
}
struct CEXAMPLE
{
unsigned int size;
constexpr CEXAMPLE(const char* s): size(myStrlen(s))
{
}
};
int main(void)
{
CEXAMPLE c(pruVar);
unsigned int size = myStrlen(pruVar);
void* a = malloc(c.size + size);
if (a != nullptr)
return 0;
else
return 1;
}
在示例中 CEXAMPLE::CEXAMPLE 在编译时求值,包括其中对 myStrlen 的调用,但在 main 中对 myStrlen 的调用在运行时求值。我必须知道的唯一方法是查看 assembler.This 网站也非常有用:http://gcc.godbolt.org/
如果您知道如何让编译器对此或类似的事情发出警告,我将不胜感激
myStrlen(pruVar)
可以在编译时求值;在这种情况下,编译器只是选择不这样做。
如果你想强制编译器在编译时评估它,或者如果这是不可能的错误,请将结果分配给 constexpr
变量:
constexpr unsigned int size = myStrlen(pruVar);
^^^^^^^^^
您也可以使用 enum
或 std::integral_constant
:
enum : unsigned int { size = myStrlen(pruVar) };
std::integral_constant<unsigned int, myStrlen(pruVar)> size;
基于必须在编译时评估模板参数这一事实,可以使用辅助模板。
namespace helper {
template<class T, T v> constexpr T enforce_compiletime() {
constexpr T cv = v;
return cv;
}
}
#define compiletime(arg) ::helper::enforce_compiletime<decltype(arg), (arg)>()
这允许在没有额外的 constexpr 变量的情况下执行编译时,这对于计算值查找表很方便。
constexpr uint32_t bla(uint8_t blub) {
switch (blub) {
case 5:
return 22;
default:
return 23;
}
}
struct SomeStruct {
uint32_t a;
uint32_t b;
};
SomeStruct aStruct = {compiletime(bla(5)), compiletime(bla(6))};