无法使用 T = vector<T::iterator> 创建递归类型
Can't create recursive type `using T = vector<T::iterator>`
我正在尝试创建一个包含自己的迭代器作为元素的向量,但我发现无法完全扩展类型声明。
using MyVectorType = std::vector<std::vector<...>::iterator>;
// Trying to fill in the ... ^^^
另一种失败的方法是:
using MyVectorType = std::vector<MyVectorType::iterator>;
use of undeclared identifier 'MyVectorType'
Trying to use an intermediate declaration also fails
template <class T>
using MyVectorType_incomplete = std::vector<T>;
using MyVectorType = MyVectorType_incomplete<MyVectorType_incomplete::iterator>;
error: 'MyVectorType_incomplete' is not a class,
namespace, or enumeration
显然使用指针可以解决这个问题。
struct It {
It *iterator;
};
vector<It>;
但是这意味着您不能使用迭代器接口,基本上必须为给定的 class.
重新实现迭代器
有没有办法在 C++ 中做到这一点?
更一般地说,有没有一种方法可以像上面那样创建递归类型,在类型创建之前引用它?
using
引入了类型别名。别名是其他事物的名称。您始终可以用其他东西替换别名。事实上,您必须这样做才能找出涉及别名的类型的属性,因为别名没有自己的属性。
using MyVectorType = std::vector<MyVectorType::iterator>; // replace the name with the thing named
using MyVectorType = std::vector<std::vector<MyVectorType::iterator>::iterator>; // again
using MyVectorType = std::vector<std::vector<std::vector<std::vector<MyVectorType::iterator>::iterator>; ::iterator>::iterator>; // and again and again
所以你不能有递归类型别名。
您可以创建递归类型,但不能使用类型别名关闭循环。您可以使用指针或模板来完成。像这样的东西应该是合法的 C++:
struct my_vector : public std::vector<std::vector<my_vector>::iterator> {}
但不知道对你有多大用处
我不认为这是可能的标准。
要实现你想要的,你必须能够参考 std::vector<T>::iterator
而 T
是不完整的。
在 C++17 之前,T
需要完整才能实例化 std::vector<T>
,因此它无法在那里工作。
自 C++17 起,标准允许使用不完整的类型 T
实例化 std::vector<T>
,但是只要类型在其任何成员被引用之前是完整的,请参阅 [vector.overview]/4 post-C++20 草稿。
但是,如果要实现这样的递归,需要能够继承或者拥有std::vector<T>::iterator
类型的成员。这不仅引用了 ::iterator
类型,而且还需要对其进行实例化,此时不保证可以正常工作。
让 class 继承自 std::vector<T::iterator>
也不会起作用,因为那时 T
需要完成。将 T::iterator
推迟到另一个继承的 class 也不会起作用,因为 classes 然后递归地依赖于在另一个之前完成。
根据标准库的实现方式std::vector<T>::iterator
,以下可能有效,但根据标准,它在技术上是未定义的行为:
struct MakeMyVectorType : std::vector<MakeMyVectorType>::iterator {
};
using MyVectorType = std::vector<MakeMyVectorType>;
int main() {
MyVectorType v1(10);
MyVectorType v2(v1.begin(), v1.end());
v2.push_back({v1.begin()+5});
MyVectorType v3{{v2.begin()}, {v2.end()}};
std::cout << v1.size() << "\n"; // 10
std::cout << v2.size() << "\n"; // 11
std::cout << v3.size() << "\n"; // 2
}
我也不确定你会如何使用这种类型。
我正在尝试创建一个包含自己的迭代器作为元素的向量,但我发现无法完全扩展类型声明。
using MyVectorType = std::vector<std::vector<...>::iterator>;
// Trying to fill in the ... ^^^
另一种失败的方法是:
using MyVectorType = std::vector<MyVectorType::iterator>;
use of undeclared identifier 'MyVectorType' Trying to use an intermediate declaration also fails
template <class T>
using MyVectorType_incomplete = std::vector<T>;
using MyVectorType = MyVectorType_incomplete<MyVectorType_incomplete::iterator>;
error: 'MyVectorType_incomplete' is not a class,
namespace, or enumeration
显然使用指针可以解决这个问题。
struct It {
It *iterator;
};
vector<It>;
但是这意味着您不能使用迭代器接口,基本上必须为给定的 class.
重新实现迭代器有没有办法在 C++ 中做到这一点?
更一般地说,有没有一种方法可以像上面那样创建递归类型,在类型创建之前引用它?
using
引入了类型别名。别名是其他事物的名称。您始终可以用其他东西替换别名。事实上,您必须这样做才能找出涉及别名的类型的属性,因为别名没有自己的属性。
using MyVectorType = std::vector<MyVectorType::iterator>; // replace the name with the thing named
using MyVectorType = std::vector<std::vector<MyVectorType::iterator>::iterator>; // again
using MyVectorType = std::vector<std::vector<std::vector<std::vector<MyVectorType::iterator>::iterator>; ::iterator>::iterator>; // and again and again
所以你不能有递归类型别名。
您可以创建递归类型,但不能使用类型别名关闭循环。您可以使用指针或模板来完成。像这样的东西应该是合法的 C++:
struct my_vector : public std::vector<std::vector<my_vector>::iterator> {}
但不知道对你有多大用处
我不认为这是可能的标准。
要实现你想要的,你必须能够参考 std::vector<T>::iterator
而 T
是不完整的。
在 C++17 之前,T
需要完整才能实例化 std::vector<T>
,因此它无法在那里工作。
自 C++17 起,标准允许使用不完整的类型 T
实例化 std::vector<T>
,但是只要类型在其任何成员被引用之前是完整的,请参阅 [vector.overview]/4 post-C++20 草稿。
但是,如果要实现这样的递归,需要能够继承或者拥有std::vector<T>::iterator
类型的成员。这不仅引用了 ::iterator
类型,而且还需要对其进行实例化,此时不保证可以正常工作。
让 class 继承自 std::vector<T::iterator>
也不会起作用,因为那时 T
需要完成。将 T::iterator
推迟到另一个继承的 class 也不会起作用,因为 classes 然后递归地依赖于在另一个之前完成。
根据标准库的实现方式std::vector<T>::iterator
,以下可能有效,但根据标准,它在技术上是未定义的行为:
struct MakeMyVectorType : std::vector<MakeMyVectorType>::iterator {
};
using MyVectorType = std::vector<MakeMyVectorType>;
int main() {
MyVectorType v1(10);
MyVectorType v2(v1.begin(), v1.end());
v2.push_back({v1.begin()+5});
MyVectorType v3{{v2.begin()}, {v2.end()}};
std::cout << v1.size() << "\n"; // 10
std::cout << v2.size() << "\n"; // 11
std::cout << v3.size() << "\n"; // 2
}
我也不确定你会如何使用这种类型。