funkcja operująca na klasie wewnętrznej

0

Mam problem z przekazywaniem klas wewnętrznych jako argumenty funkcji. Dla kodu:

template <typename T>
class jakas_klasa
{
	public:
		struct klasa_wewnetrzna
		{
			//jakies dane
		};
		//reszta klasy
};

template <typename T>
void func (typename jakas_klasa<T>::klasa_wewnetrzna x)
{
	//kod
}

int main()
{
	jakas_klasa<int>::klasa_wewnetrzna x;
	func (x);
	return 0;
}

kompilator wypluwa:

wd.cpp: In function 'int main()':
wd.cpp9: error: no matching function for call to 'func(jakas_klasa<int>::kla
sa_wewnetrzna&)'
wd.cpp9: note: candidate is:
wd.cpp55: note: template<class T> void func(typename jakas_klasa<T>::klasa_w
ewnetrzna)

Przy zprecyzowaniu w mainie:

int main()
{
	jakas_klasa<int>::klasa_wewnetrzna x;
	func<int> (x);
	return 0;
}

Program się kompiluje i działa, ale chciałbym żeby można było tej funkcji używać bez precyzowania, tak jak to było w listingu wyżej. Jak to zrobić?

0

w takim razie musisz sprecyzować to w funkcji

void func(jakas_klasa<int>::klasa_wewnetrzna x) {}

0

Jest to jakieś rozwiązanie, ale nadal jest uciążliwe. Chodzi o to że parametrem szablonu powinien być dowolny typ, i nie mam pojęcia jaki zostanie użyty więc nie jestem w stanie zprecyzować wszystkich możliwych funkcji. Nie mogę też wymagać tego od osoby która będzie używała tego szablonu - takie są założenia zadania.

0

Nie da się tego zrobić w ten sposób. Dedukcja parametru szablonu jest w tym wypadku niemożliwa. Szczegóły: http://stackoverflow.com/questions/7178948/problem-with-functions-accepting-inner-classes-of-template-classes

0

Dzięki. Czyli jednak to zadanie bedzie bardziej skompikowane niz mi się wydawało :)

mam jeszcze pytanie co sądzicie o takim rozwiązaniu tego problemu ?:

template <typename T>
class jakas_klasa
{
	public:
		struct klasa_wewnetrzna
		{
			void unikatowa_metoda_klasy_wewnetrznej() 
			{
				//moze nic nie robic
			}
			//jakies dane
		};
		//reszta klasy
};

template <typename T>
void func (T x)
{
	x.unikatowa_metoda_klasy_wewnetrznej();
	//kod
}

int main()
{
	jakas_klasa<int>::klasa_wewnetrzna x;
	func (x);
	return 0;
}

Dzięki temu jedynie obiekty klasy wewnętrznej (posiadające unikatową metodę) będą mogły być używane jako argumenty funkcji. Ale wydaje mi się że jest to trochę mało eleganckie rozwiązanie.

0

Dlaczego przeszkadza Ci konieczność specyfikowania typu? Przecież i tak go znasz. Możesz sobie go nawet stypedefować.

0

Nie znam typu. To był tylko przyklad, o typie wiem tylko tyle że ma konstruktor, operatory porownania (==, !=), przypisania (=) i że można go przesłać do strumienia(<<). Nie wiem jak będzie wyglądała funkcja main, mam napisać tylko klasę.

0

Ten, kto będzie wywoływał metodę będzie doskonale wiedział co to za typ, który ma tam wpisać. Szablony w C++ są przecież statyczne - wszystko musi być znane w czasie kompilacji.

0

a nie możesz czasem zdefiniować tej struktury poza klasą?

0

Właśnie w zadaniu jest określone że to musi być klasa wewnętrzna, tworzenie oiektu tej klasy musi wygladać tak:

klasa_zewnetrzna<parametr1, parametr2>::klasa_wewnetrzna nazwa_zmiennej;

Jeszcze będę musiał się trochę namęczyć z funkcjami zaprzyjaźnionymi do tej klasy.

0

no to jeżeli naprawdę nie chcesz podawać tych parametrów do funkcji i w samej funkcji też nie chcesz ich określać to jedyne wyjście żeby struktura wewnętrzna dziedziczyła po jakimś wspólnym interfejsie (klasie abstrakcyjnej) i wtedy do tej funkcji przyjmujesz tylko ten interfejs, a struktury wewnętrzne zrzutują się do tego interfejsu zostawiając tylko wspólne cechy (bo wtedy tylko jest możliwe zrobienie wspólnej funkcji)

albo pokaż lepiej całe zadanie jakie masz zrobić

0

Cała treść zadania jest w tym pdfie:
http://programowanie.ii.uj.edu.pl/problems/7//Tablica.pdf

mam w tym zadaniu problem przy klasie Index, która musi dostarczać przeciążony operator wypisania do strumienia (<<). Z tego co udało mi się napisać wyszło:

template <typename T>
class A
{
	public:
	class B
	{
		private:
			int b;
		public:
			B(int i):b(i){}
			friend ostream& operator << (ostream& o, B& b)
			{
				return o<<b.b;
			}
	};
};

wcześniej próbowałem wyrzucić definicję poza klasę:

template <typename T>
class A
{
	public:
	class B
	{
		private:
			int b;
		public:
			B(int i):b(i){}
			template <typename U>
			friend ostream& operator << (ostream& o, typename A<U>::B& a);
	};
};

template <typename T>
ostream& operator << (ostream& o, typename A<T>::B& b)
{
	return o<<b.b;
}

Ten kod się kompilował, ale linker rzucał błędami.

Wszystkie klasy są dość symbolicznie napisane. W rozwiązaniu zadania będą dodatkowe elementy w kalsach i pozmieniane nazwy, ale żeby się łatwiej połapać uprościłem kod.

Chodziło mi o to że już chyba wiem jak napisać ten program, ale umieściłem poprzedniego posta dla tych którzy są ciekawi na czym polegało dokładnie to zadanie.

0
D napisał(a)

Dzięki temu jedynie obiekty klasy wewnętrznej (posiadające unikatową metodę) będą mogły być używane jako argumenty funkcji. Ale wydaje mi się że jest to trochę mało eleganckie rozwiązanie.

Na pewno one zle nie jest bo przecież z takiego sposobu kozystaja algorytmy STL. One też przyjmuja np. vector<int>::iterator it.

 
template <class InputIterator, class OutputIterator>
  OutputIterator copy ( InputIterator first, InputIterator last, OutputIterator result );

Tak samo rozwiązano problem front_insert_iterator. Może to i nie funkcja, ale problem ten sam. Kontener musi posiadać push_front, a gdy jej nie ma to wiadomo.

http://cplusplus.com/reference/std/iterator/front_insert_iterator/

0

Z tego co widzę w zadaniu Index nie musi być podtypem. I raczej nie powinien być aby nie wiązać indeksu z typem danych coby z kolei można było używać te same indeksy wymiennie na tablicach przechowujących obiektu różnego typu:

template <unsigned N>
struct SparseArrayIndex { /* ... */ };

template <typename T, unsigned N>
struct SparseArray {
    typedef SparseArrayIndex<N> Index;
    /* ... */
};
0

Indeks powinen byc klasą wewnętrzną ponieważ dla tablicy 3-wymiarowej potrzebny jest indekx {x,y,z}, a dla 2-wymiarowej {x,y} itd.

0
D napisał(a)

Indeks powinen byc klasą wewnętrzną ponieważ dla tablicy 3-wymiarowej potrzebny jest indekx {x,y,z}, a dla 2-wymiarowej {x,y} itd.
Nie widzę związku. Jak popatrzysz na przykład który podałem to spełnia on postawione wymagania. Indeks jest powiązany z liczbą wymiarów więc użycie go w tablicy o innej ilości wymiarów wygeneruje błąd kompilacji. Ten zabieg z przykładu powinien uprościć implementację.

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