-3

I am currently trying to write my first template class as an assignment for my c++ class, but I don't understand why I keep getting this error:

g++ -c main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:12:14: error: cannot convert ‘Dequeu<int>’ to ‘int’ in initialization
  int ou = i[0];

main.cpp:

#include "main.h"
#include <stdio.h>
#include <iostream>

using namespace std;
int main (int args, char ** argc){

    Dequeu<int>* i = new Dequeu<int>();

    i->push_back (10);

    int ou = i[0];

    cout<<"i[0]: "<<ou<<endl;
}

with main.h:

#include "Dequeu.h"

dequeu.h:

#ifndef MAIN_H
#define MAIN_H
#endif

#include "Node.h"
#include <stddef.h> //NULL

template<typename T>
class Dequeu {
public:
    Dequeu();   ~Dequeu();

    void push_back(T);

    T &operator[] (int i) {
        if (i<size && i>=0){

            //head?
            if (i == 0)
                return head->value;
            //tail?
            if (i == size-1)
                return tail->value;

            //other:
            Node<T>* temp = head;
            i--;

            while (i != 0 ){
                temp = temp->next;
                i--;
            }

            return temp->Value();
        }
    }

private:
    Node<T> * head;
    Node<T> * tail;
    int size;
};

template<typename T>
Dequeu<T>::Dequeu() {
    head->nullify();
    tail->nullify();
}

template<typename T>
Dequeu<T>::~Dequeu(){
    Node<T>* temp = head;

    while (temp->Next() != NULL) {
        temp = temp->next;
        delete(head);
        head=temp;
    }
}

template<typename T>
void Dequeu<T>::push_back(T t){
    Node<T>* newNode;

    newNode->Value(t);
    newNode->prev = tail;

    tail->next = newNode;
    tail = newNode;

    if (head == NULL)
        head = tail;

    size++;
}

and Node.h:

#include <stddef.h> //NULL

template <typename T>
class Node {
public:
    Node<T>* prev;
    Node<T>* next;
    T value;

    Node(); ~Node();

    void nullify ();

private:
};

template <typename T>
void Node<T>::nullify() {
    this->value = NULL;
    this->next = NULL;
    this->prev = NULL;}

The last thing I tried was event just returning this->head->value without checking the input integer in operator[].

The class is not finished yet, so don't wonder why there are only two functions implemented...

Please feel free to tell me how to write this code better if you find something very bad in it, I am really bad in this.

Dominik Reinert
  • 1,075
  • 3
  • 12
  • 26

3 Answers3

6
Dequeu<int>* i = new Dequeu<int>();
int ou = i[0];

Since i is a pointer, i[0] does not mean calling operator[] on Dequeu<int>, it is essentially the same as *i.

What you mean is int ou = (*i)[0];, but really i shouldn't be a pointer in the first place, you should just create it like so:

Dequeu<int> i;
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • Thank you, but creating it with `Dequeu i = new Dequeu();` gives me `main.cpp:8:34: error: conversion from ‘Dequeu*’ to non-scalar type ‘Dequeu’ requested Dequeu i = new Dequeu();` – Dominik Reinert Jan 05 '16 at 09:31
  • 1
    Don't create it with `Dequeu i = new Dequeu();`, use `Dequeu i;`. You don't need dynamic allocation here. – TartanLlama Jan 05 '16 at 09:33
  • I'm guessing you're coming from a Java background. `new` in Java and C++ are completely different concepts. – TartanLlama Jan 05 '16 at 09:38
  • Yeah, coming from Java - I already hate C++.. Have to deal with the circular reference and have no clue how to solve it - though there are many posts on this (offtopic, I know..) – Dominik Reinert Jan 05 '16 at 09:52
  • Not to sound mean, but perhaps you hate C++ because you are trying to treat it like Java? The languages are completely different and trying to directly translate idiomatic coding from one language to the other will only bring pain. The fundamental C++ concepts at play here are allocation, object lifetimes and pointers; all of which are different from any Java features. – TartanLlama Jan 05 '16 at 09:55
  • This is totally right! But how should I be able to do this with no guidance, after 2 (!) months of C++ and 3 years of Java? If I had the time to "learn" it, it would be no problem, but being forced to "do it, no matter how" is not the way to handle completely new concepts from scratch - besides the other courses I have to do. – Dominik Reinert Jan 05 '16 at 09:58
  • I would recommend picking up one of [these](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) introductory books and working your way through it. "Accelerated C++" is pretty succinct and should teach you all the important concepts, which will save you time in the long run. – TartanLlama Jan 05 '16 at 10:01
  • okay, thank you, will do this. one last question: when forward declaring the `Node` - how and where to do this? I get `Node is not a template class` error? – Dominik Reinert Jan 05 '16 at 10:02
  • 1
    Like `template class Node;`. Best to forward declare at the top of a file in which you are using `Node` but don't need the full definition (like a header file with a declaration of a function taking a `Node` by reference). – TartanLlama Jan 05 '16 at 10:05
  • segmentation fault -.- thank you anyway! – Dominik Reinert Jan 05 '16 at 10:09
1

When you have containers like Vector / Deque etc, there is no specific reason to use the same pointer (*)

just use pain Deque instead of Deque *

The inbuilt overload takes care of almost all the things

Daksh Gupta
  • 7,554
  • 2
  • 25
  • 36
1

Your main question, i.e. the compilation error, has already been answered by TartanLlama.

However, you also ask: "Please feel free to tell me how to write this code better if you find something very bad" so I'll add this answer for other parts.

It seems you have misunderstood the pointer concept through out the code. When you define a pointer to an element of some type, you'll get a pointer to an element of some type and nothing more! You will not get an element of that type.

Example:

SomeType* ptrA;  // Just a pointer - it is not pointing to an instance of SomeType
                 // The pointer should never be used/dereferenced until 
                 // it has been initialized to point to a real element.

SomeType* ptrB = new SomeType; // Now you have a pointer which points to 
                               // an instance of SomeType.
                               // Now you can use the pointer to operate on the element.

Looking at some of your code:

template<typename T>
Dequeu<T>::Dequeu() {
    head->nullify();  // Illegal. head is uninitialized and not pointing to a Node<T>
    tail->nullify();  // Illegal. tail is uninitialized and not pointing to a Node<T>
}

The code would normally look like:

template<typename T>
Dequeu<T>::Dequeu() {
    head = nullptr;
    tail = nullptr;
}

Same kind of problem here:

template<typename T>
void Dequeu<T>::push_back(T t){
    Node<T>* newNode;  // newNode is just a pointer - there is no Node<T> element

    newNode->Value(t);  // Illegal - see above
    newNode->prev = tail;

    tail->next = newNode; // Illegal - tail may be nullptr
    tail = newNode;

    if (head == NULL)
        head = tail;

    size++;
}

You need a redesign. Something like:

template<typename T>
void Dequeu<T>::push_back(T t){
    Node<T>* newNode = new Node<T>; // Create a new Node<T> and have newNode point at it

    newNode->Value(t);

    if (head == nullptr)
    {
        newNode->prev = nullptr;
        newNode->next = nullptr;
        head = newNode;
        tail = newNode;
        size = 1;
        return;
    }

    if (tail == nullptr) throw some_exception....

    // Add code to insert newNode at the back

    size++;
}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63