使constexpr在OSX上的C ++ 17中与pow一起使用

问题描述 投票:1回答:1

我正在尝试获得一个用C ++ 17编写的可在OSX(Mojave)上运行的基于Linux的项目。大部分内容都可以正常编译,直到获得该文件为止:ClassName.hpp

class ClassName {

public:

    static constexpr double DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1 = 2; // represents 0.99
    static constexpr double DEFAULT_TARGET_TFINAL_DIGITS_FROM_0 = 10; // represents 1e-10
    static constexpr double DEFAULT_TARGET_INITIAL_PBAD = (1-pow(10,-DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1));
    static constexpr double DEFAULT_TARGET_FINAL_PBAD = pow(10,-DEFAULT_TARGET_TFINAL_DIGITS_FROM_0);
    static constexpr double DEFAULT_ERROR_TOL_DIGITS = 0.9; // as a fraction of digits in the last place from the above.
    static constexpr double DEFAULT_SAMPLE_TIME = 1;

    // more unrelated code
};

编译时,出现以下错误:

error: constexpr variable
     'DEFAULT_TARGET_INITIAL_PBAD' must be initialized by a constant expression
 ...double DEFAULT_TARGET_INITIAL_PBAD = (1-pow(10,-DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1));
           ^                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ClassName.hpp: note: non-constexpr function 'pow<int, double>'
     cannot be used in a constant expression
   static constexpr double DEFAULT_TARGET_INITIAL_PBAD = (1-pow(10,-DEFAULT_TARGET_TINITI...
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/math.h:968:1: note:
     declared here
pow(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT

因此出于某种原因,它可以在Ubuntu和CentOS上运行。我认为这与pow的定义有关?但是我不确定如何解决它,或者甚至是问题所在。我还尝试过从constexprDEFAULT_TARGET_TINITIAL_DIGITS_FROM_1中删除DEFAULT_TARGET_TFINAL_DIGITS_FROM_0并将其设置为const,但仍然遇到相同的问题。

c++ macos compiler-errors constexpr
1个回答
1
投票

首先,您无法使用标准C ++ 17中不是constexprconstexpr不是std::pow的函数来初始化constepxr类成员。解决方法是声明它们为const。尽管它们不能在需要编译时间const的地方使用,但它们是不可变的。传统方法是在标头中声明它们,并根据需要将其包括在源文件中。然后,您需要一个定义静态const成员的实现文件。

如果您的代码需要编译时为const或constexpr,则唯一的选择是编写自己的pow

这是在执行main()之前使用显示技术的问题的一部分,使用不是constexpr的函数初始化const静态的一种方法:

创建标头constinit.h,声明该类

// include header guards
// declare the static consts
struct ClassName {
    static double DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1; // represents 0.99
    static double DEFAULT_TARGET_INITIAL_PBAD; // to be initialized by pow
};

创建一个初始化静态文件的实现文件:

#include "constinit.h"
#include <cmath>

double ClassName::DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1{ 2 }; // represents 0.99
double ClassName::DEFAULT_TARGET_INITIAL_PBAD = (1 - std::pow(10, -DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1));

使用静态变量:

#include <iostream>
#include "constinit.h"


int main()
{
    std::cout << ClassName::DEFAULT_TARGET_INITIAL_PBAD << std::endl;
}

如果需要constexpr进行编译时初始化,则需要定义自己的constexpr pow函数。这在C ++ 17中有效:

    #pragma once // or header guards per your preference

constexpr double my_pow(double x, int exp)
{
    int sign = 1;
    if (exp < 0)
    {
        sign = -1;
        exp = -exp;
    }
    if (exp == 0)
        return x < 0 ? -1.0 : 1.0;
    double ret = x;
    while (--exp)
        ret *= x;
    return sign > 0 ? ret : 1.0/ret;
}
class ClassName {
public:
    static constexpr double DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1 = 2; // represents 0.99
    static constexpr double DEFAULT_TARGET_TFINAL_DIGITS_FROM_0 = 10; // represents 1e-10
    static constexpr double DEFAULT_TARGET_INITIAL_PBAD = (1 - my_pow(10, -DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1));
    static constexpr double DEFAULT_TARGET_FINAL_PBAD = my_pow(10, -DEFAULT_TARGET_TFINAL_DIGITS_FROM_0);
    static constexpr double DEFAULT_ERROR_TOL_DIGITS = 0.9; // as a fraction of digits in the last place from the above.
    static constexpr double DEFAULT_SAMPLE_TIME = 1;

    // more unrelated code
};
© www.soinside.com 2019 - 2024. All rights reserved.