Reputation: 3
I have constexpr object constructor with constexpr methods.
// My SparseArray implementation
#include <cstdint>
#include <iostream>
#include <utility>
template<typename T, uint64_t size>
class SparseArray
{
public:
using ElementType = T;
template<typename... Args>
constexpr SparseArray(Args&&... args)
: values{args...} {
std::cout << "Args ctor." << '\n';
}
template<uint8_t Index>
constexpr ElementType get() const {
// some logic
return T();
}
constexpr auto someMethod() {
get<0>(); // <--------- works fine
auto seq = std::integer_sequence<ElementType, 0>{}; // <--------- works fine
auto seq2 = std::integer_sequence<ElementType, get<0>()>{}; // <-- error
}
ElementType values[size];
};
int main ()
{
SparseArray<int, 3> array(1, 2, 3);
array.someMethod();
return 0 ;
}
But I really need to use method in such compile-time context. I'm going to sum two constexpr objects in compile-time, so I need to get data of both thanks to get method.
=======Edited=====
After @chris answer I understood that I missed one thing. Actually get method looks like this:
template<uint8_t Index>
constexpr ElementType get() const {
if(/*some logic*/)
return values[/*some logic*/];
else
return T();
}
So, the code deals with data member of the object.
Upvotes: 0
Views: 3858
Reputation: 61910
constexpr
functions have to be usable at compile-time and runtime. You're calling a non-static member function, so it needs to work regardless of whether the class object is known at compile-time. If you require the object to be known at compile-time, the function no longer works at runtime.
The easiest way around this is to use a function that doesn't depend on the unused class object:
template<uint8_t Index>
static constexpr ElementType get() {
// some logic
return T();
}
If that isn't an option because you are using the class object, then you need to ensure that object is constexpr to use it:
constexpr SparseArray<int, 3> array(1, 2, 3);
auto seq2 = std::integer_sequence<int, array.get<0>()>{};
Regardless of where you use get
, the only way the result is going to be usable as a compile-time value is if all parameters, including the object, are compile-time values.
EWG has accepted constexpr!
to force compile-time evaluation of a function, but it wouldn't make your original example compile until used with a constexpr SparseArray
object.
Upvotes: 3