提问人:Chris 提问时间:6/23/2023 最后编辑:Nicol BolasChris 更新时间:6/23/2023 访问量:64
名为 Queue 的类的实例不能以某些方式初始化,但可以以其他方式初始化,这两种方式对我来说似乎几乎相同
An instance of a class named Queue can't be initialized in some ways but can in others and both ways seem almost identical to me
问:
我一直在努力寻找一个更好的标题。 错误如下:错误 C2440:“initializing”:无法从“initializer list”转换为“Queue” 这似乎是我遇到的一个非常常见的错误,我希望这是一个常见的错误。 问题发生在运算符中<< :
template <typename T>
std::ostream& operator<<(std::ostream& out, bsTree<T>& tree) {
if (!tree.m_root)
return out;
using Nodeptr = typename bsTree<T>::Node*;
Queue<Nodeptr> q{ tree.m_root }; //this line right here
Nodeptr current{tree.m_root};
while (!q.empty()) {
current = q.front();
std::cout << current->data << '\n';
if (current->left)
q.push(current->left);
if (current->right)
q.push(current->right);
q.pop();
}
return out;
}
在队列中:
template <std::same_as<T>... Args>
Queue(Args&&... args) {
push(std::forward<T>(args)...);
}
似乎问题在于编译器推断为 T 的内容与实际的参数类型之间存在一些差异。 这是 Queue 中唯一的构造函数,另一个不带任何参数。 如果 std::same_as 被替换为 typaname,问题就会消失,所以这有一些东西,我想知道它是什么。与 std::same_as 一样,如果我使用函数返回树根节点的地址,那么它就可以工作,但是如果它返回对保存根地址的私有成员变量的引用,那么它又不起作用。 奇怪的是,当我在运算符中定义一个 Nodeptr 变量时<<并使用 tree.m_tree 初始化它,然后使用它来初始化不起作用的队列。这似乎与使用函数获取树的根地址相同(例如,如果我没有将运算符<< bsTree 的朋友,那么我将不得不使用一个函数),但它不起作用,我很好奇为什么它不会。 使用简单的 typename...似乎解决了所有这些情况下的所有问题。 我想我现在会使用它,我会回来看看发生了什么:)
我试过打字名...而不是 std::same_as...我本以为问题会消失...... 我也只是有一个想法,即编译器可能会创建引用。为了测试这一点,我在运算符中尝试了这个<<
using Nodeptr = typename bsTree<T>::Node*;
Nodeptr current{ tree.m_root };
Nodeptr temp{ current };
Queue<Nodeptr> q{ std::move(temp)};
所以这奏效了,所以我想我应该使用一些 std 概念来删除引用等来获得裸露的类型。 我试过这个:
template <std::same_as<std::remove_cvref_t<T>>... Args>
Queue(Args&&... args) {
push(std::forward<T>(args)...);
}
我想由于某种原因仍然不正确,这给出了相同的错误(删除 std::move 后) 欢迎任何建议,提前谢谢大家。
答:
所以这有效,所以我想我应该使用一些标准概念来删除 引用等来获取裸类型。
您可以使用 -子句进行检查requires
template <typename... Args>
requires (std::same_as<T, std::remove_cvref_t<Args>> && ...)
Queue(Args&&... args) {
push(std::forward<T>(args)...);
}
评论
template<class...Ts>Queue(Ts&&... args) requires (std::conjunction_v<std::is_same<T,std::remove_reference_t<Ts>>...>) {push( std::forward<Ts>(args)... );}