当 class 已完全定义时,为什么我会得到 "invalid use of incomplete type"?
Why do I get "invalid use of incomplete type", when the class is fully defined?
我知道当基数 class 仅向前声明时会发生这种类型的错误,但就我而言,据我所知它已完全实现:
我正在尝试创建一个单位系统,该系统只有在使用正确的单位时才会编译,使用文字和代数运算符。
我从基础 class 单元开始,它只是 T 的包装器,并被所有其他单元继承。
然后我定义允许的代数运算符,它应该 return 正确的单位。
我明白了
error: invalid use of incomplete type ‘class Units<T>’
[build] 107 | return Mps{static_cast<T>(rhs) / static_cast<T>(lhs)};
对于此代码:
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
}
看起来编译器很困惑,警告具有误导性。提供缺少的模板参数以修复它:
return Mps<T>{static_cast<T>(rhs) / static_cast<T>(lhs)};
^^^
如果您希望避免明确指定参数,您可以(可能)定义一个演绎指南。
其他问题:
- 缺少分号。
- 你的运算符是针对浮点数的,但你在1_km中使用整数;那是行不通的。要么使用浮点文字,要么为整数添加重载。
using typename Units<T>::Units;
是错误的。丢掉 typename
.
我知道当基数 class 仅向前声明时会发生这种类型的错误,但就我而言,据我所知它已完全实现:
我正在尝试创建一个单位系统,该系统只有在使用正确的单位时才会编译,使用文字和代数运算符。
我从基础 class 单元开始,它只是 T 的包装器,并被所有其他单元继承。
然后我定义允许的代数运算符,它应该 return 正确的单位。
我明白了
error: invalid use of incomplete type ‘class Units<T>’
[build] 107 | return Mps{static_cast<T>(rhs) / static_cast<T>(lhs)};
对于此代码:
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
}
看起来编译器很困惑,警告具有误导性。提供缺少的模板参数以修复它:
return Mps<T>{static_cast<T>(rhs) / static_cast<T>(lhs)};
^^^
如果您希望避免明确指定参数,您可以(可能)定义一个演绎指南。
其他问题:
- 缺少分号。
- 你的运算符是针对浮点数的,但你在1_km中使用整数;那是行不通的。要么使用浮点文字,要么为整数添加重载。
using typename Units<T>::Units;
是错误的。丢掉typename
.