使用模板理解 constexpr 函数 [C++]

Understanding constexpr functions with templates [C++]

我正在尝试了解 C++ 中的 constexpr 函数。我无法理解第一个函数定义有什么问题。我认为所有的变量都应该在编译时可用。

我正在使用 Catch2 作为测试库。

sqrtfunc.hpp

#include <stdexcept>
#include <numeric>

template <class T>
constexpr T max_iterations = std::numeric_limits<T>::max_exponent();

template <class T>
constexpr T epsilon = std::numeric_limits<T>::epsilon();

// This function definition doesn't work
template <class T>
constexpr T sqrtFunc(T x){
    if(x < 0){
        throw std::domain_error("Argument must be >= 0");
    }
    else if(x == 0){
        return x;
    }

    const T c = x;
    T xn = x;
    size_t i = 0;
    while (i < max_iterations<T>){
        T xnplus_1 = xn - (sqr(xn) - c) / ( 2 * xn);
        if (abs(xnplus_1 - xn) <= epsilon<T>){
            break;
        }
        xn = xnplus_1;
        i++;
    }
    return xn;
}

// This function definition works
template <class T>
constexpr T sqrtFunc(T x){
    if(x < 0){
        throw std::domain_error("Argument must be >= 0");
    }
    else if(x == 0){
        return x;
    }

    const T c = x;
    T xn = x;
    // size_t i = 0;
    while (true){
        T xnplus_1 = xn - (sqr(xn) - c) / ( 2 * xn);
        if (abs(xnplus_1 - xn) <= epsilon<T>){
            break;
        }
        xn = xnplus_1;
        // i++;
    }
    return xn;
}

test_file.cpp

TEST_CASE("SQRT"){
    SECTION("Square root"){
        constexpr double var = 4.0;

        REQUIRE(sqrtFunc(var) == Approx(2.0).margin(0.0001));
    }
}

第一个函数声明的错误如下:

error C2064: term does not evaluate to a function taking 0 arguments

 note: see reference to variable template 'const T max_iterations<double>' being compiled
          [
              T=double
          ]
 note: see reference to function template instantiation 'T sqrtFunc<double>(T)' being compiled
          [
              T=double
          ]

对于具有第二个声明的完全相同的 cpp 文件,我得到了正确的输出。

如果有帮助,我正在使用 Visual Studio 2017。C/C++ Optimizing Compiler Version 19.16.27045 for x86

注意:我已经进行了所有必要的导入 (#include)。

您正在调用 std::numeric_limits<T>::max_exponent,但它是一个变量,而不是一个函数。