以下(一般)情况:
我正在尝试在一个类中调用另一个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;
}
答案 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;
}