Reputation: 1470
Following (generic) situation:
I am trying to call another constexpr
member-function within a class, but I get the error that 'this' is not a constant expression
. The question I now have is (as I am new to the constexpr
idiom), is if such a use-case is not allowed. Otherwise, how would I fix it?
#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;
}
Upvotes: 2
Views: 531
Reputation: 275220
So constexpr
does not mean "this function can only be called at compile time". It means "this function may be called both at compile and run time".
char x=testM2<testM1<varbase>()>();
If called at run time, the value of this
is not a compile time constant. So the result of a constexpr
method call is not a compile time value, so its result cannot be used as a template argument.
If you are not using this
(as you appear not to be) then marking testM2
etc. as static
fixes your problem. If you are using this
then there isn't a simple workaround; there is no way to say "this function will only be called at compile time". Any workaround will depend on details of what you are doing with this
and the return value, if even possible. Write a new question with those details added.
Upvotes: 2
Reputation: 870
The problem is that every instance of cc
will have its own version of doSomething()
, testM1()
and testM2()
.
To solve it, the compiler will apply this
in front of all the functions, to identify which instance of cc
you are trying to refer to.
this
is not a constant expression. It is evaluated at runtime.
That is why you are getting the error : 'this' is not a constant expression
To solve this problem, either move your constexpr
functions outside the class, or mark these functions as static
.
Here is a working revision of your code, which will work in C++11 as well.
#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;
}
Upvotes: 1