【问题标题】:nested calls to constexpr functions对 constexpr 函数的嵌套调用
【发布时间】:2019-01-24 08:23:38
【问题描述】:

以下(一般)情况:

我试图在一个类中调用另一个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

【问题讨论】:

  • constexpr 函数可以在非constexpr 上下文中调用。我怀疑它们不能用作模板参数。
  • 只需将testM1testM2 标记为static。你想要做的就像constexpr void foo(int i) { std::array&lt;int, i&gt; arr; }。这是不允许的。
  • 问题是cc 的每个实例都有自己的doSomething()testM1()testM2() 版本。为了解决这个问题,编译器将在所有函数前面应用this,以识别您尝试引用的cc 的哪个实例。 this 不是常量表达式。它在运行时进行评估。要解决此问题,请将您的 constexpr 函数移到类外,或将这些函数标记为 static

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


【解决方案1】:

所以constexpr 并不是说​​“这个函数只能在编译时调用”。意思是“这个函数可以在编译和运行时调用”。

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

如果在运行时调用,this 的值不是编译时常量。所以constexpr方法调用的结果不是编译时值,所以它的结果不能用作模板参数。

如果您没有使用this(您似乎没有使用),那么将testM2 等标记为static 可以解决您的问题。如果您使用的是this,那么没有简单的解决方法;没有办法说“这个函数只会在编译时调用”。任何解决方法都将取决于您对 this 所做操作的详细信息以及返回值(如果可能的话)。写一个添加了这些细节的新问题。

【讨论】:

    【解决方案2】:

    问题是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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-10
      • 2017-01-28
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多