Warunek dołączenia metody do klasy szablonowej

0

Cześć wszystkim. Mam specyficzne pytanie odnośnie szablonów/klas :).
Czy jest możliwość określenia warunku, w którym metoda jest dołączana do klasy szablonowej, bądź staje się publiczna/prywatna? Ewentualnie, czy jest możliwe dodanie do dziedziczenia warunku, albo dynamiczna zmiana dostępu do metody?
Warunkiem takim byłaby sytuacja, w której tworzony jest szablon klasy, ale o określonym typie, np int/float (nakaz użycia wbudowanych typów) choćby poprzez sprawdzenie za pomocą typeid...
Istnieje co prawda sposób na ograniczenie tworzenia szablonów za pomocą biblioteki boost (std::is_integra, std::is_fundamentall), lecz czy istnieje sposób na zupełne ukrycie takiej metody/funkcji (zamiast ewentualnego ostrzeżenia od kompilatora w przypadku niewłaściwego użycia szablonu)?

0

Czy można zmienić widoczność (publiczna/prywatna) albo inaczej określić czy metoda ma być dostępna w zależności od parametru szablonu - nic nie przychodzi mi do głowy (std::enable_if dla funkcji szablonowej, owszem). Czy można to zrobić dynamicznie? No tak, wsadź if i rzucaj wyjątek, jeżeli typeid pokaże, że typ jest nieprawidłowy (niedobre rozwiązanie, bo nie wiadomo co zwróci typeid w ogólnym przypadku) Jeżeli chodzi o dziedziczenie to można tak:

#include <iostream>

template <typename T>
class Functionality {

};

template <>
class Functionality<int> {
public:
  void function() {
    std::cout << "Boo!\n";
  }
};

template <typename T>
class StrangeClass : public Functionality<T> {
    
};

int main() {
  StrangeClass<int> c1;
  StrangeClass<float> c2;
  
  c1.function();
  
  // A to sie nie skompiluje:
  //c2.function();
	
  return 0;
}

Co do tych rzeczy z boost, to boost już nie jest do nich potrzebny. To jest w standardzie.

Opisz co Ty dokładnie kombinujesz, bo coś mi się wydaje, że konieczność robienia czegoś takiego może być efektem błędu w projekcie.

0

Stworzyłem klasę, która w założeniu jest listą (coś jak vector), w klasie tej mam metodę sortowania bąbelkowego, która działa prawidłowo na zmiennych fundamentalnych (lub innych z możliwym operatorem <). Chcę ograniczyć szablon tejże metody wyłącznie do zmiennych podstawowych.
Znalazłem następujące rozwiązanie (przykład prostej klasy):

#include <type_traits>
#include <iostream.h>
template <class T>
class Lol {
	public:
		template<class T>
		typename std::enable_if<std::is_fundamental<T>::value, T>::type
		foo1()
		{
			std::cout << "bla bla\n";
			return 0;
		}
};

main:
Lol <int> zonk; // okej
zonk.foo1<int>();  // okej

Lol <string> str; //okej
str.foo1<string>(); // blokada użycia metody :)

Error wynikający z blokady:

[BCC32 Error] File1.cpp(90): E2285 Could not find a match for 'Lol<string>::foo1<T>()'
  Full parser context
    File1.cpp(80): parsing: int wmain(int,wchar_t * *)

Taki sposób podoba mi się ze względu na to, że w razie niedozwolonego typu szablonu metody wyskoczy komunikat o błędzie, zamiast skoczyć w kompilatorze gdzieś głębiej (lokalizując problem). Natomiast nie podoba mi się użycie konkretyzacji szablonu przy każdorazowym wywołaniu. Lecz co jest pozytywne - w momencie wystukania na klawiaturze "zonk." kompilator podpowiada mi co znajduje się w klasie. Natomiast w metodzie kolegi powyżej tejże podpowiedzi nie ma w ogóle (co skutkuje nakazem pamiętania o metodzie). Ponad to... w moim przypadku definiuje klasę/metodę tylko RAZ.
Zastanawiałem się po prostu czy nie ma możliwości ukrycia szablonu metody, który nie spełnia kryteriów [to znaczy, widoczny tylko w odpowiednim szablonie (przez wpisanie "zonk." - a co za tym idzie... Jak myślę... usunięcie jawnego konkretyzowania szablonu przy wywołaniu ( czyli "zonk.foo1()" zamiast "zonk.foo1<int>()" ) ].

P.S. Jeśli chodzi o sens budowania takiej klasy to odpowiem następująco: Całą tą klasę tworze aby się lepiej zorientować w CPP :).

0

wg mnie powinno zadziałać:
template<> typename std::enable_if<std::is_fundamental<T>::value, T>::type foo1() ...

1

Żeby nie musieć pisać zonk.foo1<int>(); wystarczy zmienić ten kawałek:

template<class Tf = T>
typename std::enable_if<std::is_fundamental<Tf>::value, Tf>::type

To powinno spełniać wszystkie Twoje wymagania.

1

w klasie tej mam metodę sortowania bąbelkowego, która działa prawidłowo na zmiennych fundamentalnych (lub innych z możliwym operatorem <)

Ja tutaj w ogóle nie widzę tutaj potrzeby wykluczania specjalizacji. Szablony z C++ to nie generics z C#/Javy, gdzie musisz nakładać constraints. W C++ jest nim sam kod. Jeżeli wymagasz od typu tego, by miał zdefiniowany operator < to skorzystaj z niego w kodzie i tyle. To taki szablonowy duck type'ing.
Obecnie tylko sztucznie ograniczasz możliwości klasy oraz zmieniasz treść błędu.

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