jaj16839
jaj16839

Reputation: 23

How can I specialize a operator function type by class template

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

Answers (1)

aparpara
aparpara

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

Related Questions