据我所知,当函数内部的每个值均为const且使用的函数为constexpr时,也肯定会在编译时评估constexpr函数,而constexpr也仅使用const值。此外,另一篇文章指出,可以通过使返回的obj常量来强制进行编译时编译。
所有这些陈述都是错误的。见下文。
否,只有在需要(编译时)常量表达式的上下文中调用constexpr
函数时,才保证在编译时对调用进行评估。 obj2
的初始值设定项不是这样的上下文,即使它是const
。
您可以通过将obj2
声明为constexpr
来强制初始化程序进行编译时评估。 (然而,其含义与const
完全不同!)
即使那样它也不起作用,因为calculations<double,size>(obj1)
实际上不是常量表达式。 obj1
也是一个编译时常量,也没有声明它constexpr
。同样,这是行不通的,因为test1
也不是一个常量表达式,而无需声明constexpr
。
然后,您还需要制作Array
constexpr
的构造函数,并且实际上需要在test1
内填充calculations
的值,因为访问未初始化的值会导致未定义的行为行为的不确定性使表达式不是常量表达式。
总而言之:
template<int Size,typename T>
struct Array{
T array[Size];
constexpr Array(const T * a) {
for(int i = 0; i < Size; i++){
array[i] = a[i];
}
}
};
template<typename T,int size>
class Example{
private:
Array<size,T> _array;
public:
constexpr explicit Example(T * arr):_array(arr){};
constexpr explicit Example(const T * arr):_array(arr){};
};
template<typename D,int size,typename ...buf,typename T>
constexpr auto calculations(const T & myObj){
D test1[2];
test1[0] = 0;
test1[1] = 1;
// calculation fills arr
return Example<D,size>(test1);
}
int main(){
const int size = 2;
constexpr double test1[size] = {1,2};
constexpr auto obj1 = Example<double,size>(test1); //compile time
//obj2 calculations during compile time or run-time?
constexpr auto obj2 = calculations<double,size>(obj1);
}
在C ++ 20中,将有一个替代关键字consteval
可以代替函数上的constexpr
使用,以强制其始终在编译时求值 。时间。目前,如果不进行例如返回值的目的地constexpr
变量。
实际上,您的原始代码具有未定义的行为。由于Array
没有constexpr
构造函数,因此永远不能在常量表达式中构造该类型的对象。并且由于Example
使用该类型,因此它也不能在常量表达式中使用。这使将constexpr
放在其构造函数上是非法的,因为如果没有至少一组有效的模板参数和函数参数会产生常量表达式,则声明为constexpr
的函数会导致未定义的行为。 (这同样适用于calculations
,因为它使用Example
。
因此,如果程序的格式正确,则必须 将constexpr
放在Array
的构造函数中。
在常量表达式(例如,calculations
内内部中创建的变量是否为const
都是无关紧要的。
,
来自微软:
constexpr函数是其返回值可以在以下位置计算的函数
消费代码需要时进行编译。消费代码要求
编译时的返回值,例如,初始化一个
constexpr变量或提供非类型模板参数。当它
参数是constexpr值,constexpr函数产生一个
编译时常数。当使用非constexpr参数调用时,或者
当在编译时不需要它的值时,它将在
运行时间像常规功能一样。 (这种双重行为使您免于
必须编写相同的constexpr和非constexpr版本
功能。)
因此,如果所有参数均为constexpr,则您的calculate函数将评估编译时间
本文链接:https://www.f2er.com/3132381.html