Как я могу специализировать тип функции оператора по шаблону класса - PullRequest
2 голосов
/ 05 мая 2019

У меня есть класс, подобный следующему, и я хочу специализировать оператор '->' шаблоном класса T. Специализация должна зависеть от того, является ли тип T типом указателя или нет.Я искал решения, но не нашел решения для этой конкретной проблемы.

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
}

Спасибо за любую помощь!

1 Ответ

1 голос
/ 05 мая 2019

Вам нужно частичная специализация А также вы должны быть осторожны с указателями разыменования. Ваш исходный пример может привести к сбою.

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';
}
...