Używanie klasy w niej samej.

0

Cześć :D
Po długiej przerwie musiałem wrócić na chwilę do C++ i napotkałem już pewne zagwozdki których nie mogę rozwikłać.
Mianowicie, czy jest możliwe, żeby zdefiniować jakąś swoją własną klasę, i w tej klasie utworzyć kolekcję obiektów tego samego typu? Przykładowo :

#ifndef CLIENT_H
#define CLIENT_H

#include<deque>
using namespace std;
class Client
{
public:
	deque<Client> kolejka;
	void start(deque<Client> q);
};
#endif

Powyższy kod wywala błąd przy kompilacji :
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\include\deque(593,1): error C2027: wykorzystanie niezdefiniowanego przez użytkownika typu "Client"
1>C:\Users\mswar\source\repos\ConsoleApplication2\ConsoleApplication2\Client.h(7): message : zobacz deklarację „Client”
1>C:\Users\mswar\source\repos\ConsoleApplication2\ConsoleApplication2\Client.h(10): message : zobacz odwołanie do kompilowanego tworzenia wystąpienia „std::deque<Client,std::allocator<Client>>” klasy klasa szablon

Czy jest w stanie ktoś udzielić porady ? :D
Z góry dziękuję

1

Po co chcesz to zrobić? Przecież taki zapis jest bez sensu. To wygląda jakby programista C uczył się C++. Jeśli robiłeś kolejki w C, to w C++ tak się nie robi. Można, ale w większości przypadków to bez sensu.

0

GCC łyka bez problemu ale MSVC kręci nosem.

0

Tak, w MSVC próbowałem.

2

jeśli chodzi o wskaźnik lub referencję, a klasa by była w danym miejscu jeszcze nieznana *), to używa się "forward declaration" która wygląda:

class Client;

Nie jest to zadowalające, jeśli w miejscu użycia potrzebna jest pełna wiedza o klasie, np w celu rezerwacji przestrzeni na obiekt - tylko referencja lub wskażnik.

**update: **co do jakości kodu, przyłączam się do głosów na "nie", z wielu powodów, od using std i w ogóle.

*) można mniemać, że MSVC klasę traktuje jako nieznaną aż do końca jej definicji - wydaje się, ze nie narusza tym standardu.

0

Zdaje się że deque, choć z nazwy jest kolejką, to raczej jest wektorem. Może musi więc wiedzieć, ile miejsce zarezerwować na Client, więc klasa musi być skończona.
To może zleżeć to jednak od implementacji. Tu działa: https://godbolt.org/z/ee5Gj591v

Choć patrząc na to co napisałeś... nie chciałeś aby stworzyć singieltona? Bo bez tego to taki potworek. Client ma kolejkę obiektów Client, z których każdy ma kolejkę obiektów Client, a każdy z nich ma...

0

Nawet jeśli to się skompiluje to nie jest to dobra praktyka. Ale nie ma problemu przechowywać kolekcji wskaźników czy referencji do „typu własnego”. Ten client ma się dodać do kolekcji jako referencja, czy ma się do niej skopiować? I kto ma zarządzać jego czasem życia?

0

Kręcicie nosem na taką konstrukcję, a gdyby ktoś w Haskellu napisał

data Client = KolejkaKlientów [Client]

to by nikt nie marudził.

Jak najbardziej taka struktura ma sens. A czemu to w MSVC nie działa, nie wiem. Zawsze myślałem, że powinno działać.

1

@enedil: nie działa, bo:

The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type is a complete type and meets the requirements of Erasable, but many member functions impose stricter requirements.

https://en.cppreference.com/w/cpp/container/deque

To raczej dziwne, że na GCC działa ;)

EDIT: @DarkFerret zobacz to: https://stackoverflow.com/questions/6349822/incomplete-type-in-class-which-has-a-member-of-the-same-type-of-the-class-itse

Tylko jakbyś chciał używać shared_ptr z wewnątrz klasy to przeczytaj jeszcze to:
https://en.cppreference.com/w/cpp/memory/enable_shared_from_this

Albo wrzuć to co wymyśliłeś to Ci ktoś podpowie pewnie.

0

Clang też akceptuje kod OPa. 2:1, MSVC demokratycznie przegrywa :]

2

OFFTOPIC:
using namespace std; - w pliku nagłówkowym to poważny błąd!

2

https://godbolt.org/z/8Whjfeeo4

Jak widać z std::vector działa.
Różnica zapewne musi wynikać z innej implementacji std::deque dla MSVC, musi być coś co wymaga znania rozmiaru klasy już podczas instancji szablonu.
std::vector nie ma takiego wymogu.

std::vector - cppreference.com

T - The type of the elements.

T must meet the requirements of CopyAssignable and CopyConstructible. (until C++11)
The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type is a complete type and meets the requirements of Erasable, but many member functions impose stricter requirements. (since C++11) (until C++17)
The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type meets the requirements of Erasable, but many member functions impose stricter requirements. This container (but not its members) can be instantiated with an incomplete element type if the allocator satisfies the allocator completeness requirements. (since C++17)

Jak widać std::vector najpierw dostał wymóg, że T jest konpletnym typem w C++11, a w C++17 to poluzowało.
Zapewne wynika to z tego, że działąło przed C++11 i działa wszędzie dalej na C++11, więc odpuścili.

std::deque po wprowadzeniu ograniczenia na kompletność typu T, wymóg jest nadal utrzymany.

std::deque - cppreference.com

T - The type of the elements.

T must meet the requirements of CopyAssignable and CopyConstructible. (until C++11)
The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type is a complete type and meets the requirements of Erasable, but many member functions impose stricter requirements. (since C++11)

Więc MSVC jest bliżej prawdy, a clang i gcc postanowiły utrzymać kompatybilność z przed C++11

0

http://eel.is/c++draft/vector.overview#4

Z drugiej strony w deque nie znajdziemy ani jednej zapiski o tym, czy T musi być complete type, czy nie. Jak widać w postach wcześniej jest to implementation defined, jednak standard nic o tym nie wspomina.
http://eel.is/c++draft/deque.overview

0

Możesz wskaźnik zrobić na ten sam typ jak np w liście, ale też bym się zastanawiał po co chcesz coś takiego?

1 użytkowników online, w tym zalogowanych: 0, gości: 1