对constexpr函数的嵌套调用

时间:2018-08-17 09:59:40

标签: c++ c++11 nested c++14 constexpr

以下(一般)情况:

我正在尝试在一个类中调用另一个constexpr成员函数,但是出现了'this' is not a constant expression错误。我现在遇到的问题是(因为我是constexpr惯用语),是否允许这种用例。否则,我该如何解决?

#include <iostream>

class cc
{
public:
    cc()=default;
    ~cc()=default;

    // public method to call th eprivate constexpr functions
    template<int varbase>
    constexpr void doSomething()
    {
        static_assert(varbase>0, "varbase has to be greater zero");
        // nested call to constexpr functions
        char x=testM2<testM1<varbase>()>();
    }

private:

    template<int var1>
    constexpr int testM1()
    {
     int temp=var1;
     return (++temp);
    }

    template<int var2>
    constexpr char testM2()
    {
        int temp=var2;
        if (temp==2)
            return 'A';
        else
            return 'B';
    }
};

int main()
{
    cc obj;
    obj.doSomething<1>();
    return 0;
}

Run the above example

2 个答案:

答案 0 :(得分:1)

因此constexpr并不意味着“只能在编译时调用此函数”。这意味着“可以在编译和运行时都调用此函数”。

    char x=testM2<testM1<varbase>()>();

如果在运行时调用,则this的值不是编译时间常数。因此,constexpr方法调用的结果不是编译时间值,因此其结果不能用作模板参数。

如果您没有使用this(看起来好像不是),则将testM2等标记为static可以解决您的问题。如果您使用的是this,则没有简单的解决方法。没有办法说“仅在编译时调用此函数”。任何解决方法都将取决于您对this进行的操作的详细信息以及返回值(如果可能)。写一个新问题并添加这些细节。

答案 1 :(得分:0)

问题在于cc的每个实例都将具有自己的doSomething()testM1()testM2()版本。
为了解决这个问题,编译器将在所有函数之前应用this,以标识您要引用的cc实例。

this不是常量表达式。在运行时进行评估。
这就是为什么出现错误的原因:'this' is not a constant expression

要解决此问题,请将您的constexpr函数移到类之外,或将这些函数标记为static

这是您的代码的有效修订版,也可以在C ++ 11中使用。

#include <iostream>

template<int var1>
constexpr int testM1() // move these functions outside, if they use no data of class cc
{
    return int{var1 + 1};
}

template<int var2>
constexpr char testM2()
{
    return (var2 == 2) ? 'A' : 'B';
}

class cc
{
public:
    cc()=default;
    ~cc()=default;

    // public method to call the private constexpr functions
    template<int varbase>
    static constexpr void doSomething() 
    {
        /* if you want to keep it inside class, mark it `static` 
           so that the compiler understands that it will be shared by all instances. */
        static_assert(varbase>0, "varbase has to be greater zero");
        // nested call to constexpr functions
        constexpr char x = testM2<testM1<varbase>()>(); // preferably x should be `constexpr`
    }
};

int main()
{
    cc obj;
    obj.doSomething<2>();
    return 0;
}