D
D
Dmitry2016-05-22 23:17:58
OOP
Dmitry, 2016-05-22 23:17:58

How to put a "non-trivial" object in a structure?

Good time of the day!
I don’t know how to formulate my question correctly, since I encountered this for the first time, searched a bunch of forums, but I didn’t really understand what the point was.
I have the following project structure. (In a truncated format and without implementing methods, I will insert only existing constructors)

class Point : public PointBase
{
public:
  Point(double X, double Y, double Z)
  {
  }

private:
  double X;
  double Y;
  double Z;
};

class Edge : public EdgeBase
{
public:
  Edge(Point* firstPoint, Point* secondPoint)
  {
    this->firstPoint = firstPoint;
    this->secondPoint = secondPoint;
  }
private:
  Point* firstPoint;
  Point* secondPoint;
};

template<typename type_t>
struct item
{
  item* next;
  type_t data;
};

template <typename type_t>
class Array : public ArrayBase
{
public:
  Array();

  friend class IArray<typename type_t>;

private:
  item<type_t> *head;
  item<type_t> *tail;
};

template <class type_t>class Array;

template <class type_t>
class IArray
{
public:
  IArray() {};
  IArray(Array<type_t>&);

private:
  Array<type_t>* arr;
  item<type_t>* currentItem;
};

class Model : public ModelBase
{
public:
  Model();
  Model(const Model& model) 
  {
  };

  Model& operator=(const Model& model)
  {
  }

private:
  IArray<Point> points;
  IArray<Edge> edges;

  Model(Model&&);
};

Next, for example in the IArray class (an iterator for the Array class), I want to make a function to add an element.
But when trying to allocate memory,
item<type_t>* newItem = new item<type_t>;
the error C2280 "item::item(void)": attempting to reference a deleted function pops up, supposedly an attempt to reference a deleted function, as a function it requires a constructor for the item structure (?_?)
When adding all kinds of constructors ( in general, for the first time I actually come across a structure requiring constructors, given that I have already done a similar project)
(I limited myself to these, I don’t know what else to add)
template<typename type_t>
struct item
{
  item* next;
  type_t data;
  item() {};
  item(const item<type_t>&) {};
  item(item<type_t>&&) {};
};

An error pops up that a constructor suitable default constructor for Edge was not found (~_~ was found for the Point type)
What exactly is the matter here, I have no idea, the only assumption is that in Edge we actually store another object only a pointer to it), although I do not know how this can affect.
I would be very grateful if someone could help me figure out this situation and suggest a possible solution. Thanks in advance!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mercury13, 2016-05-23
@HaseProgram

One of the fields (in this case data, the implementation item<Edge>) does not have a default constructor. There are three ways.
ONCE. Figure out how to make the constructor still exist.

class Edge : public EdgeBase
{
public:
  Edge (Point* firstPoint, Point* secondPoint) { init(firstPoint, secondPoint); }
  Edge () { init(NULL, NULL); }
  void init (Point* firstPoint, Point* secondPoint)
  {
    this->firstPoint = firstPoint;
    this->secondPoint = secondPoint;
  }
private:
  Point* firstPoint;
  Point* secondPoint;
};

TWO. If the object is copied / transferred, you can use such a thing. With your permission, I will simplify the task and instead of Edge I will start another class - ImmutableInt. True, this code is an attempt to combine a hedgehog with a snake (it is not clear what concept Payload should support), but, nevertheless, it works.
#include <iostream>

class ImmutableInt
{
public:
    explicit ImmutableInt(int x) : fData(x) {}
    int data() const { return fData; }
private:
    int fData;
};

template <class Payload>
class ListItem
{
public:
    Payload payload;
    ListItem* next;

    ListItem() : next(NULL) {}
    ListItem(const Payload& x) : payload(x), next(NULL) {}
};

// Так писать нельзя — эта конструкция расшаблонивает все функции,
// а конструктора по умолчанию как не было, так и нет!
//template class ListItem<ImmutableInt>;

int main()
{
    ListItem<ImmutableInt> li(ImmutableInt(42));
    std::cout << li.payload.data() << std::endl;
    return 0;
}

THREE. Take advantage of C++11 variadic templates.
#include <iostream>

class ImmutableInt
{
public:
    explicit ImmutableInt(int x) : fData(x) {}
    int data() const { return fData; }
private:
    int fData;
};

template <class Payload>
class ListItem
{
public:
    Payload payload;
    ListItem* next = nullptr;

    template<class... Args>ListItem(Args... args) : payload(args...) {}
};

int main()
{
    ListItem<ImmutableInt> li(42);
    std::cout << li.payload.data() << std::endl;
    return 0;
}

PS Although ImmutableInt is semantically the same int and theoretically explicitnot necessary, I nevertheless noted it - just to show that in the second case we pass ImmutableInt<42> as a parameter, and in the third - 42.
PPS I mentioned the word "concept". This is a set of type requirements. Something like an interface - but, firstly, it has nothing to do with OOP and its dynamic polymorphism, and, secondly, not so rigid: how do you use an interface from Java to establish the concept of “there is a copy constructor” or “can divide itself into number and something comes out"? Syntax support for concepts is deferred to C++17, but there were already several concepts in C++03: InputIterator, DefaultConstructible, CopyAssignable, and others. In the meantime ... the concept is not supported - a compilation error is somewhere in the terrible standard header.
PPPS By writing the code
template<typename type_t>
struct item
{
  item* next;
  type_t data;
};

you automatically required the concept of DefaultConstructible from type_t (there is a default constructor)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question