A po co Ty masz się zabezpieczać? Zrobi to za Ciebie kompilator. Jeśli wykorzystasz w tym szablonie któryś z typów wbudowanych i będziesz chciał skorzystać z operatora -> to dostaniesz błąd na poziomie kompilacji. Przeciążając taki operator jasno dajesz do zrozumienia, iż chodzi ci o klasy definiowane przez użytkownika, więc użycie typów wbudowanych jest z założenia błędem, który trzeba rozwiązywać właśnie na poziomie kompilacji.
Natomiast jeśli chciałbyś korzystać z tego szablonu dla klas i typów wbudowanych (z np. tym zastrzeżeniem, że dla typów nie będzie operatora ->) to skorzystaj z częściowej specjalizacji szablonów klas. Przykład:
template <typename T, bool type = false>
class AaA
{
private :
T *a;
public:
T *operator->()
{
return a;
}
};
template <typename T>
class AaA<T, true>
{
private :
T *a;
public:
};
void func()
{
AaA<std::string> obj1;
AaA<int, true> obj2;
obj1->empty();
}