C++ 聚合的类型不完整,无法使用模板类定义
c++ aggregate has incomplete type and cannot be defined with template class
这是我第一次遇到无法通过简单的谷歌解决的问题。 我在 c++ 中作业分配有问题。作为初创公司,我们不允许更改主要.cpp。 任务是编写双链表并使用模板类。
我收到错误
aggregate Queue<std::__cxx11::basic_string<char> > q1' has incomplete type and cannot be defined Queue<string> q1;
和
variable 'Queue<double> q3' has initializer but incomplete type
Queue<double> q3(q2);
如果我用谷歌搜索这些错误,那么 ansare 是,我可能没有在头文件中正确声明我的类或类似的声明或定义错误。但我找不到我犯的错误。
我已经尝试了构造函数的不同配置(带和不带初始值设定项列表(。我尝试了特殊化。如果我将 friend 运算符<<的特殊化放在头文件中(我认为总是这样做(,我会收到此错误:
expected initializer before '<' token
std::ostream& operator<< <std::string>
我希望你能帮助我。
这是主要的.cpp不应该改变:
#include <iostream>
#include <iomanip>
#include <ctime>
#include <utility>
#include <string>
#include "Queue.hpp"
using namespace std;
int main()
{
cout << boolalpha;
Queue<string> q1;
cout << "Queue q1 ist leer: " << q1.empty() << endl << endl;
q1.push("Bergische");
q1.push("Universitaet");
q1.push("Wuppertal");
cout << "Queue q1:" << endl << q1 << endl;
cout << "Pop erstes Element: " << q1.pop() << endl << endl;
cout << "Queue q1:" << endl << q1 << endl;
Queue<double> q2;
q2.push(3.1415);
q2.push(2.7182);
cout << "Queue q2:" << endl << q2 << endl;
cout << "Groesse von q2: " << q2.size() << endl << endl;
Queue<double> q3(q2);
cout << "Queue q3 aus q2 mit Copy-Konstruktor: " << q3 << endl;
Queue<int> q4;
for(int i=0; i<100000000; ++i)
q4.push(i);
cout << "Groesse von q4: " << q4.size() << endl;
cout << fixed << setprecision(8);
cout << "Beginne Zeitmessung Copy-Konstruktor... " << flush;
clock_t start = clock();
Queue<int> q4copy(q4);
clock_t end = clock();
cout << (end-start)/(double)CLOCKS_PER_SEC << " Sekunden" << endl;
cout << "Groesse von q4: " << q4.size() << endl;
cout << "Groesse von q4copy: " << q4copy.size() << endl;
cout << "Beginne Zeitmessung Move-Konstruktor... " << flush;
start = clock();
Queue<int> q4move(move(q4));
end = clock();
cout << (end-start)/(double)CLOCKS_PER_SEC << " Sekunden" << endl;
cout << "Groesse von q4: " << q4.size() << endl;
cout << "Groesse von q4move: " << q4move.size() << endl;
return 0;
}
队列.hpp:
#ifndef QUEUE_HPP_
#define QUEUE_HPP_
#include <iostream>
#include <iomanip>
#include <ctime>
#include <utility>
#include <string>
template<typename T>
class Queue;
template<typename T>
class Queue_el{
private:
Queue_el* pHeadEl;
Queue_el* pTailEl;
T data;
public:
Queue_el(Queue_el* a = nullptr, Queue_el* b = nullptr);
Queue_el(const Queue_el &q);
~Queue_el();
Queue_el& operator=(Queue_el q);
friend class Queue<T>;
template<typename U>
friend std::ostream& operator<<(std::ostream& os, const Queue_el<U> &q);
};
template<typename T>
class Queue{
private:
Queue_el<T>* pHead;
Queue_el<T>* pTail;
public:
Queue(Queue_el<T>* a = nullptr, Queue_el<T>* b = nullptr);
Queue(const Queue &q);
~Queue();
Queue(Queue&& q);
Queue& operator=(const Queue&q);
Queue& operator=(Queue&& q);
void push(T data) const;
T pop() const;
bool empty() const;
int size() const;
friend class Queue_el<T>;
template <typename U>
friend std::ostream& operator<<(std::ostream& os, const Queue<U> &q);
};
template<> class Queue_el<std::string>;
template<> class Queue_el<double>;
template<> class Queue_el<int>;
template<> class Queue<std::string>;
template<> class Queue<double>;
template<> class Queue<int>;
#endif /* QUEUE_HPP_ */
和队列.cpp:
#include "Queue.hpp"
template<typename T>
Queue<T>::Queue(Queue_el<T>* a, Queue_el<T>* b)
:pHead(a), pTail(b)
{
};
template<typename T>
Queue<T>::Queue(const Queue<T> &q) {
Queue_el<T> *buffer = nullptr;
Queue_el<T> *bufferq = q.pHead;
buffer = new Queue_el<T>;
pHead = buffer;
buffer = buffer->pTailEl;
bufferq = bufferq->pTailEl;
while (bufferq->pTailEl != nullptr){
buffer = new Queue_el<T>;
*buffer = *bufferq;
buffer = buffer->pTailEl;
bufferq = bufferq->pTailEl;
}
pTail = buffer;
}
template<typename T>
Queue<T>::~Queue() {
if (pHead != nullptr) {
Queue_el<T> *buffer1 = pHead;
Queue_el<T> *buffer2 = pHead;
while (buffer1->pTailEl != nullptr) {
buffer1 = buffer1->pTailEl;
delete buffer2;
buffer2 = buffer1;
}
delete buffer1;
}
}
template<typename T>
Queue<T>::Queue(Queue<T> &&q){ //move Konstruktor
pHead = q.pHead;
pTail = q.pTail;
q.pHead = nullptr;
q.pTail = nullptr;
}
template<typename T>
Queue<T>& Queue<T>::operator=(const Queue<T> &q) {
if (this != &q) {
if (pHead != nullptr) {
Queue_el<T> *buffer1 = pHead;
Queue_el<T> *buffer2 = pHead;
while (buffer1->pTailEl != nullptr) {
buffer1 = buffer1->pTailEl;
delete buffer2;
buffer2 = buffer1;
}
delete buffer1;
pHead = nullptr;
pTail = nullptr;
}
if (q.pHead != nullptr) {
Queue_el<T> *buffer = pHead;
Queue_el<T> *bufferq = q.pHead;
do {
buffer = new Queue_el<T>;
*buffer = *bufferq;
buffer = buffer->pTailEl;
bufferq = bufferq->pTailEl;
} while (bufferq->pTailEl != nullptr);
pTail = buffer;
}
}
return *this;
}
template<typename T>
Queue<T>& Queue<T>::operator=(Queue<T> &&q) {
if(this != &q){
pHead = q.pHead;
pTail = q.pTail;
q.pHead = nullptr;
q.pTail = nullptr;
}
return *this;
}
template<typename T>
void Queue<T>::push(T data) const {
if (pTail != nullptr) {
pTail->pTailEl = new Queue_el<T>;
pTail->pTailEl->pHeadEl = pTail;
pTail = pTail->pTailEl;
*pTail = data;
} else {
pTail = new Queue_el<T>(data);
pHead = pTail;
}
return;
}
template<typename T>
T Queue<T>::pop() const {
if (pHead != nullptr) {
if (pHead->pTailEl != nullptr) {
Queue_el<T> *buffer = pHead;
pHead = pHead->pTailEl;
pHead->pHeadEl = nullptr;
std::cout <<"Pop here: ";
return buffer;
} else {
Queue_el<T> *buffer = pHead;
delete pHead;
pHead = nullptr;
pTail = nullptr;
return *buffer;
}
}
}
template<typename T>
bool Queue<T>::empty() const {
if (pHead == nullptr) {
return true;
} else {
return false;
}
}
template<typename T>
int Queue<T>::size() const {
int i = 0;
if (pHead != nullptr) {
Queue_el<T> *buffer = pHead;
i++;
while (buffer->pTailEl != nullptr) {
buffer = buffer->pTailEl;
i++;
}
}
return i;
}
template<typename U>
std::ostream& operator<<(std::ostream& os, const Queue<U> &q){
if(q.pHead != nullptr){
Queue_el<U>* buffer = q.pHead;
os << buffer << std::endl;
while(buffer->pTailEl != nullptr){
buffer = buffer->pTailEl;
os << buffer << std::endl;
};
}
return os;
}
template<> std::ostream& operator<< <std::string>
(std::ostream& os, const Queue<std::string> &q);
template<> std::ostream& operator<< <double>
(std::ostream& os, const Queue<double> &q);
template<> std::ostream& operator<< <int>
(std::ostream& os, const Queue<int> &q);
template<typename T>
Queue_el<T>::Queue_el(Queue_el<T>* a, Queue_el<T>* b)
:pHeadEl(a), pTailEl(b)
{
}
template<typename T>
Queue_el<T>::Queue_el(const Queue_el<T> &q)
{
data = q.data;
pHeadEl = nullptr;
pTailEl = nullptr;
}
template<typename T>
Queue_el<T>::~Queue_el(){
std::cout << "Element zerstört" << std::endl;
}
template<typename T>
Queue_el<T>& Queue_el<T>::operator=(Queue_el<T> q){
data = q.data;
return data;
}
template<typename U>
std::ostream& operator<<(std::ostream& os, const Queue_el<U> &q){
os << q.data;
return os;
}
template<>
std::ostream& operator<< <std::string> (std::ostream& os, const Queue_el<std::string> &q);
template<>
std::ostream& operator<< <double>(std::ostream& os, const Queue_el<double> &q);
template<>
std::ostream& operator<< <int>(std::ostream& os, const Queue_el<int> &q);
在Queue.hpp
结束时,你有:
template<> class Queue_el<std::string>;
template<> class Queue_el<double>;
template<> class Queue_el<int>;
template<> class Queue<std::string>;
template<> class Queue<double>;
template<> class Queue<int>;
所有这些构造都声明了相应类模板的模板专用化Queue_el
和Queue
。
您可能想要的是显式模板实例化。语法的不同之处在于后者在template
关键字之后缺少<>
:
template class Queue_el<std::string>;
template class Queue_el<double>;
template class Queue_el<int>;
template class Queue<std::string>;
template class Queue<double>;
template class Queue<int>;
但是,请注意,这只能在完全定义模板的位置完成。因此,您需要将其放在Queue.cpp
末尾,而不是Queue.hpp
末尾:
如评论中所述
template<> class Queue<std::string>;
声明了T=std::string
的完整模板专用化,但随后不提供定义,因此Queue<std::string>
是一个不完整的类型。
如果要预编译实例化Queue<std::string>
,则应执行以下两件事:
在文件队列.hpp 末尾添加行
extern template class Queue<std::string>;
它告诉编译器在其他地方存在实例化,并阻止它创建另一个实例化。
在文件队列中.cpp在末尾添加行
template class Queue<std::string>;
这将创建头文件中
extern
语句承诺的实际实例化。
此外,如果元素类型是Queue<T>
中的嵌套类型,这将使设计更容易:则不需要单独的显式实例化。
相关文章:
- 使用QJsEngine在Qt中注册自定义类型
- 在UE4中使用未定义类型'UTextBlock'
- 修改"std::set"中用户定义类型的值
- 当我使用自定义类型创建动态数组时,即使使用字符串,它似乎也不起作用
- QtQuick - qml:28:错误:未知方法返回类型:自定义类型
- 如何使自定义类型在unordered_map中用作键
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- Qt5 远程对象 + 自定义类型,但不在 POD 中
- 为什么转换函数声明不需要至少一个定义类型说明符
- 标准::原子中的自定义类型
- 如何使用自定义类型声明Arduino数组?
- 如何在 Cython 中定义返回 cpp 定义类型的函数?
- 使用自定义访问者时具有自定义类型的提升变体失败(源自 boost::static_visitor)
- 您可以将binary_search应用于具有自定义类型的矢量吗?
- 在自定义类型图中重用 SWIG 映射
- 扩展自定义类型的spdlog
- vim使用户定义类型的COLOR与C++中的基本类型相同
- 重载自定义类型的 std::to_string 和 std::to_chars?
- 具有未声明/未定义类型的 typedef 结构
- 函数重载:内置类型与用户定义类型