对 constexpr 函数的嵌套调用
nested calls to constexpr functions
以下(通用)情况:
我试图在 class 中调用另一个 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;
}
问题是 cc
的每个实例都会有自己的 doSomething()
、testM1()
和 testM2()
版本。
为了解决这个问题,编译器将在所有函数前面应用 this
,以识别您要引用的 cc
的哪个实例。
this
不是常量表达式。它在运行时进行评估。
这就是您收到错误的原因:'this' is not a constant expression
要解决此问题,请将您的 constexpr
函数移到 class 之外,或者将这些函数标记为 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;
}
所以constexpr
并不代表"this function can only be called at compile time"。意思是"this function may be called both at compile and run time".
char x=testM2<testM1<varbase>()>();
如果在 运行 时调用,this
的值不是编译时常量。所以 constexpr
方法调用的结果不是编译时值,所以它的结果不能用作模板参数。
如果您没有使用 this
(您似乎没有使用),则将 testM2
等标记为 static
可以解决您的问题。如果您使用 this
则没有简单的解决方法;没办法说"this function will only be called at compile time"。如果可能的话,任何解决方法都将取决于您使用 this
和 return 值所做的详细信息。写一个添加了这些细节的新问题。
以下(通用)情况:
我试图在 class 中调用另一个 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;
}
问题是 cc
的每个实例都会有自己的 doSomething()
、testM1()
和 testM2()
版本。
为了解决这个问题,编译器将在所有函数前面应用 this
,以识别您要引用的 cc
的哪个实例。
this
不是常量表达式。它在运行时进行评估。
这就是您收到错误的原因:'this' is not a constant expression
要解决此问题,请将您的 constexpr
函数移到 class 之外,或者将这些函数标记为 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;
}
所以constexpr
并不代表"this function can only be called at compile time"。意思是"this function may be called both at compile and run time".
char x=testM2<testM1<varbase>()>();
如果在 运行 时调用,this
的值不是编译时常量。所以 constexpr
方法调用的结果不是编译时值,所以它的结果不能用作模板参数。
如果您没有使用 this
(您似乎没有使用),则将 testM2
等标记为 static
可以解决您的问题。如果您使用 this
则没有简单的解决方法;没办法说"this function will only be called at compile time"。如果可能的话,任何解决方法都将取决于您使用 this
和 return 值所做的详细信息。写一个添加了这些细节的新问题。