I have a simple class:
#include <variant>
struct RawDataArray{
std::variant<double*, float*> data;
template <typename T>
constexpr bool IsType() const noexcept{
return std::holds_alternative<T*>(data);
}
template <typename T>
T& operator [](const int index){
return std::get<T*>(data)[index];
}
};
int main(){
double* tmpData = new double[3];
tmpData[0] = 1;
tmpData[1] = 2;
tmpData[2] = 3;
RawDataArray rawData;
rawData.data = tmpData;
rawData[0] = 0.0;
}
However, I got:
error C2676: binary '[': 'RawDataArray' does not define this operator or a conversion to a type acceptable to the predefined operator
message : could be 'T &RawDataArray::operator [](const int)'
message : 'T &RawDataArray::operator [](const int)': could not deduce template argument for 'T'
I understand the error, but I don't know, how to write such a method. I thought that using 0.0
or 0.0f
would auto-deduce the T
. I also tried to specify variable double x = 0.0
and use this, with the same error.
You do this by making []
non-template, and returning a helper class with the right overloaded operators:
#include <iostream>
#include <variant>
struct RawDataArray
{
std::variant<double *, float *> data;
class ElemHelper
{
RawDataArray ⌖
std::size_t index = 0;
public:
ElemHelper(RawDataArray &target, std::size_t index) : target(target), index(index) {}
// Those aren't strictly necessary, but help prevent some kinds of misuse.
// Same for `&&` on the functions below.
ElemHelper(const ElemHelper &) = delete;
ElemHelper &operator=(const ElemHelper &) = delete;
template <typename T>
[[nodiscard]] operator T &() &&
{
return std::get<T *>(target.data)[index];
}
template <typename T>
const T &operator=(const T &value) &&
{
return std::get<T *>(target.data)[index] = value;
}
};
[[nodiscard]] ElemHelper operator [](std::size_t index)
{
return {*this, index};
}
};
int main()
{
RawDataArray raw_data;
raw_data.data = new double[3] {1,2,3};
raw_data[0] = 0.0;
std::cout << double(raw_data[0]) << '\n';
}
This also needs a const
overload of operator[]
, with a different helper class that overloads operator const T &
and nothing else. That's left as an exercise to the reader.