Reputation: 23
I have a class like the following and want to specialize the '->' operator by the class template T. The specialization should depend on, whether the type T is a pointer type or not. I have searched for solutions but didn't find any for this specific problem.
template <typename T>
class C
{
public:
// when T is a pointer type
T operator->()
{
return value;
}
// when T is not a pointer type
const T* operator->() const
{
return &value;
}
private:
T value;
};
void test()
{
struct Test
{
int x, y;
};
C<Test> c1;
C<Test*> c2;
c1->x = 5; // should both work
c2->x = 5; // ignoring the fact, that c2's value is undefined
}
Thanks for any help!
Upvotes: 2
Views: 46
Reputation: 2201
You need partial specialization And also you need to be careful with dereferencing pointers. Your original example is likely to crash.
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;
};
Or if you have a C++17 compatible compiler, you can use if 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;
};
To test it:
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';
}
Upvotes: 1