Вам нужно частичная специализация
А также вы должны быть осторожны с указателями разыменования. Ваш исходный пример может привести к сбою.
template <typename T>
class C
{
public:
explicit C(const T& v = T()): value(v) {}
// when T is not a pointer type
T* operator->()
{
return &value;
}
private:
T value;
};
template <typename T>
class C<T*>
{
public:
explicit C(T* v = nullptr): value(v) {}
// when T is a pointer type
T* operator->()
{
return value;
}
private:
T* value;
};
Или, если у вас есть C ++ 17-совместимый компилятор, вы можете использовать , если constexpr :
template <typename T>
class C
{
public:
explicit C(const T& v = T()): value(v) {}
// when T is not a pointer type
auto operator->()
{
if constexpr (std::is_pointer_v<T>)
return value;
else
return &value;
}
private:
T value;
};
Чтобы проверить это:
int main()
{
struct Test
{
int x, y;
};
C<Test> c1({1, 2});
Test t = {3, 4};
C<Test*> c2(&t); // Initialize the pointer with some valid address, we are going to dereference it!
c1->x = 5;
c2->x = 5;
std::cout << c1->x << ' ' << c1->y << ' ' << t.x << ' ' << t.y << '\n';
}