我使用CGAL编写了一个简单的测试程序,并遇到了以下问题:
点在上面定义为
typedef K::Point_d Point;
但我不认为这是相关的。
当我尝试按如下方式编译程序时:
const int size = 10;
Point P[size];
g ++没有问题。
如果我试图编译:
const int size = stoi("10");
Point P[size]
我收到以下错误
error: variable length array of non-POD element type 'Point' (aka 'Point_d<Cartesian_d<double,
CGAL::Linear_algebraCd<double, std::__1::allocator<double> > > >')
为什么从字符串中检索时,size被视为变量而不是const?
答案 0 :(得分:2)
C ++将特定事物定义为已定义的常量表达式,以便在编译时知道 - 请参阅constant_expression。
通常,未定义为constexpr
的函数不会通过它们。你可以尝试强制它:
#include<string>
constexpr int x = std::stoi("10");
int main() {
return 0;
}
但你会发现这仍然会导致错误:
error: call to non-constexpr function 'int std::stoi(const string&, std::size_t*, int)'
所以,你运气不好,因为stoi
不是一个常数表达式。如果你真的坚持,你可以使用你自己的实现覆盖它,例如How do I convert a C string to a int at compile time?。
答案 1 :(得分:1)
stoi 。这意味着编译器不知道数组应该有多大。 如果你想做类似的事情,你必须使用constexpr函数(constexpr function)。这些可以在编译时进行评估,然后就可以了。
答案 2 :(得分:1)
编译器不理解stoi
函数的语义。所有它看到的是你调用一个返回一个整数的函数(该函数是否可以内联并优化掉是一个单独的语义问题)。
对于编译器,
之间的语义差异很小const int size = stoi("10");
和
const int size = getchar();
正如其他答案提到的那样constexpr
是例外。我只是想我说明这个问题。
答案 3 :(得分:1)
第一个const int size = 10;
是编译时const表达式,它可以在编译期间计算,
但const int size = stoi("10")
不是编译时const表达式,因此无法编译。
std::stoi
不是在编译时评估的constexpr
函数。
如果您想拥有此功能,可能需要创建一个constexpr
函数来评估编译时间。
constexpr bool is_digit(char c) {
return c <= '9' && c >= '0';
}
constexpr int stoi_impl(const char* str, int value = 0) {
return *str ?
is_digit(*str) ?
stoi_impl(str + 1, (*str - '0') + value * 10)
: throw "compile-time-error: not a digit"
: value;
}
constexpr int to_int(const char* str) {
return stoi_impl(str);
}
int main() {
constexpr int size = to_int("10");
int arr[size];
}
这将编译; [从here复制]
答案 4 :(得分:1)
在第一个代码示例中
const int size = 10;
Point P[size];
size
的特定值可以在编译时使用 ,因为它已知(您已指定)。因此,编译器可以用特定值替换它的所有用途,而不用实际创建变量。
在第二个样本中
const int size = stoi("10");
Point P[size]
编译器无法知道该值,因为它是由stoi
函数在运行时推导出来的。因此,它无法替换数组的大小(必须事先知道它以确定现在要分配的内存),并且您会收到错误。
在C ++ 11中有 constexpr 惯用法,它允许在编译时评估一些声明为constexpr的函数。但是在你的情况下stoi
不是constexpr函数,所以你无法使用这个特定的函数实现你想要的。你可以实现自己的constexpr stoi
,但我没有看到很多,因为在这种情况下你的代码会包含这样的东西:my_constexpr_stoi("10")
,即参数总是手动编写并始终事先知道。为什么不写10
?
答案 5 :(得分:0)
为了扩展kabanus的答案,语言标准说在C ++ 11中绑定的数组必须是一个称为整数常量表达式的数组。 C ++ 17略微放松了这一点并允许更多的东西,但现在这并不重要。
This page at cppreference列出了 允许在常量表达式中执行的所有操作。它基本上引用了语言标准。
允许您的第一个示例的相关部分是8a。除非将const
变量初始化为常量表达式,否则不允许使用变量。因此,使用初始化为常量表达式的const
整数类型变量的名称是合法的,如第一个示例中所示。数值常量是常量表达式,因此size
是一个const
变量,初始化为常量表达式,即A-OK。
但是,由于第2点,如果函数调用都声明为constexpr
并且已经定义,则它们只是常量表达式。因此,对于可在代码中的数组表达式中使用的标准库函数,需要将其声明为constexpr
并在头文件中定义。
该标准没有说明stoi()
符合条件,但我认为其中没有任何内容直接禁止某些实施提供此作为扩展。