Одно из полей (в данном случае
data
в реализации
item<Edge>
) не имеет конструктора по умолчанию. Есть три пути.
РАЗ. Придумать, как сделать, чтобы конструктор всё-таки был.
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;
};
ДВА. Если объект копируется/переносится, можно воспользоваться такой штукой. С вашего позволения, упрощу задачу и вместо Edge заведу другой класс — ImmutableInt. Правда, этот код — попытка совместить ежа с ужом (непонятно, какую концепцию должен поддерживать Payload), но, тем не менее, работает.
#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;
}
ТРИ. Воспользоваться переменными шаблонами (variadic templates) C++11.
#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;
}
P.S. Хотя ImmutableInt — семантически тот же int и теоретически
explicit
не надо, всё-таки отметил — просто чтобы показать, что во втором случае мы передаём параметром ImmutableInt<42>, а в третьем — 42.
P.P.S. Я упомянул слово «концепция». Это набор требований к типу. Что-то типа интерфейса — но, во-первых, никак не связано с ООП и его динамическим полиморфизмом, и, во-вторых, не столь жёсткое: как ты интерфейсом из Java наладишь концепцию «есть конструктор копирования» или «может делить себя на число и что-то выходит»? Синтаксическая поддержка концепций откладывается на C++17, но уже в C++03 было несколько концепций: InputIterator, DefaultConstructible, CopyAssignable и другие. А пока… концепция не поддерживается — ошибка компиляции где-то в страшенном стандартном хедере.
P.P.P.S. Написав код
template<typename type_t>
struct item
{
item* next;
type_t data;
};
вы автоматически потребовали от type_t концепцию DefaultConstructible (есть конструктор по умолчанию)