通过使返回的obj恒定,即使在内部包含非常量数组的情况下,强制在编译时编译constexpr函数?

我了解了List<Integer[]> eventLst = new LinkedList<Integer[]>(new Comparator<Integer[]>() { @override public int compare(Integer[] arr1,Integer[] arr2) { return arr1[0]-arr[1]; } }); 函数以及它们何时进行编译时计算。现在,我必须要用新值填充数组,因此数组不能为constexpr

据我所知,const函数肯定是在编译时评估的,当函数内部的每个值均为constexpr且使用的函数为const时,它们也仅使用{{1 }}值。此外,另一篇文章指出,可以通过使返回的obj constexpr来强制进行编译时编译。

可以说,我的函数是const,但是内部有const数组,但是返回的对象将是constexpr。我的函数non-const是否会在编译时评估(强制执行)。

const
xiaoqingqiu22 回答:通过使返回的obj恒定,即使在内部包含非常量数组的情况下,强制在编译时编译constexpr函数?

  

据我所知,当函数内部的每个值均为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

大家都在问