为什么在这种情况下它不是 constexpr?
Why isn't it a constexpr in this case?
我有一个 strlen 的 dumb constexpr 版本,编译器在某些情况下接受它作为 constexpr,但在其他情况下它不接受,这是一个例子:
template <std::size_t MAX_SIZE>
class FixedString
{
public:
explicit FixedString(const char* str)
{
for(std::size_t i = 0; i < MAX_SIZE; i++)
{
data[i] = str[i];
}
}
char data[MAX_SIZE];
};
constexpr std::size_t constexpr_strlen(const char *str)
{
for(std::size_t i = 0; i < std::numeric_limits<std::size_t>::max(); i++)
{
if(str[i] == '[=10=]')
{
return i;
}
}
return 0;
}
// doesn't compile, compiler says non-type template argument is not a constant expression
auto make_string(const char* str)
{
return FixedString<constexpr_strlen(str)>(str);
}
int main()
{
constexpr bool IS_DEV = true;
// works fine
std::array<int, constexpr_strlen(IS_DEV ? "Development" : "Production")> arr;
// works fine
FixedString<constexpr_strlen(IS_DEV ? "Development" : "Production")> str("Develop");
// doesn't compile, compiler says variable has incomplete type 'void'
auto string = make_string("Not working");
return 1;
}
为什么 constexpr_strlen 在 make_string 函数中被认为是 constexpr 而在函数中却不是?
对于我在这里看到的,它可以在编译时计算,不是吗?
主要问题是 constexpr
函数根据定义旨在在编译时 以及 在 运行 时调用。让我们从一个更简单的例子开始:
constexpr int f(int n) { return n };
int n = 7;
// n could be modified!
f(n); // compiler cannot know which value n has at runtime,
// so the function needs to be executed at runtime as well!
f(7); // well, now right the opposite...
所以这很简单:constexpr
函数的结果也是 constexpr
,if 且仅当 all 调用函数的参数是 constexpr
本身(只有这样,函数才会在编译时求值),否则,它将是一个 运行 时间值(和函数在 运行 时评估。
Inside constexpr
函数,但是,编译器无法知道函数是否仅使用 constexpr
参数调用;所以函数参数总是需要被认为是非constexpr
。我们在这里...
(当然,make_string
甚至不是 constexpr
,但是如果 constexpr
不能假设为 constexpr
函数的参数,那么普通函数参数就更少了...)
我有一个 strlen 的 dumb constexpr 版本,编译器在某些情况下接受它作为 constexpr,但在其他情况下它不接受,这是一个例子:
template <std::size_t MAX_SIZE>
class FixedString
{
public:
explicit FixedString(const char* str)
{
for(std::size_t i = 0; i < MAX_SIZE; i++)
{
data[i] = str[i];
}
}
char data[MAX_SIZE];
};
constexpr std::size_t constexpr_strlen(const char *str)
{
for(std::size_t i = 0; i < std::numeric_limits<std::size_t>::max(); i++)
{
if(str[i] == '[=10=]')
{
return i;
}
}
return 0;
}
// doesn't compile, compiler says non-type template argument is not a constant expression
auto make_string(const char* str)
{
return FixedString<constexpr_strlen(str)>(str);
}
int main()
{
constexpr bool IS_DEV = true;
// works fine
std::array<int, constexpr_strlen(IS_DEV ? "Development" : "Production")> arr;
// works fine
FixedString<constexpr_strlen(IS_DEV ? "Development" : "Production")> str("Develop");
// doesn't compile, compiler says variable has incomplete type 'void'
auto string = make_string("Not working");
return 1;
}
为什么 constexpr_strlen 在 make_string 函数中被认为是 constexpr 而在函数中却不是?
对于我在这里看到的,它可以在编译时计算,不是吗?
主要问题是 constexpr
函数根据定义旨在在编译时 以及 在 运行 时调用。让我们从一个更简单的例子开始:
constexpr int f(int n) { return n };
int n = 7;
// n could be modified!
f(n); // compiler cannot know which value n has at runtime,
// so the function needs to be executed at runtime as well!
f(7); // well, now right the opposite...
所以这很简单:constexpr
函数的结果也是 constexpr
,if 且仅当 all 调用函数的参数是 constexpr
本身(只有这样,函数才会在编译时求值),否则,它将是一个 运行 时间值(和函数在 运行 时评估。
Inside constexpr
函数,但是,编译器无法知道函数是否仅使用 constexpr
参数调用;所以函数参数总是需要被认为是非constexpr
。我们在这里...
(当然,make_string
甚至不是 constexpr
,但是如果 constexpr
不能假设为 constexpr
函数的参数,那么普通函数参数就更少了...)