I know this type of errors occur when a base class is only forward declared, but in my case it's fully implemented as far as I can tell:
I'm trying to create a unit system which would only compile if the correct units are used, employing literals and algebraic operators.
I start with a base class Units which is just a wrapper over T, and is inherited by all the other units.
Then I define the allowed algebraic operators, which should return the correct units.
I get
error: invalid use of incomplete type ‘class Units<T>’
[build] 107 | return Mps{static_cast<T>(rhs) / static_cast<T>(lhs)};
for this code:
template<typename T>
class Units
{
protected:
T val;
public:
constexpr explicit Units(T val) : val(val) { }
constexpr explicit operator T&() { return val; }
constexpr explicit operator T() const { return val; }
constexpr auto operator<=>(const Units<T> rhs) {
return val <=> rhs.val;
}
constexpr bool operator==(const Units<T> rhs) const { return val == rhs.val; }
};
template<typename T>
class Meters : public Units<T>
{
using typename Units<T>::Units;
};
template<typename T>
class Seconds : public Units<T>
{
using typename Units<T>::Units;
};
template<typename T>
class Mps : public Units<T>
{
using typename Units<T>::Units;
};
constexpr Meters<long double> operator "" _km(long double km) {
return Meters<long double>{1000 * km};
}
constexpr Seconds<long double> operator "" _s(long double s) {
return Seconds<long double>{s};
}
constexpr Mps<long double> operator "" _mps(long double s) {
return Mps<long double>{s};
}
template<typename T>
constexpr Mps<T> operator / (const Meters<T> &&rhs, const Seconds<T> &&lhs) {
return Mps{static_cast<T>(rhs) / static_cast<T>(lhs)};
}
int main() {
return 1_km / 2_s == 500_mps
}
CodePudding user response:
Looks like the compiler is confused and the warning is misleading. Provide the missing template argument to fix it:
return Mps<T>{static_cast<T>(rhs) / static_cast<T>(lhs)};
^^^
You can (probably) define a deduction guide if you wish to avoid specifying the argument explicitly.
Other issues:
- Missing semicolon.
- Your operators are for floating point, but you use integer in 1_km; that won't work. Either use floating point literal, or add an overload for integers.
using typename Units<T>::Units;
is wrong. Lose thetypename
.