Ковариантный тип возврата с примитивными типами - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть следующее:

template<typename T>
class AbsContainer {
public:
    virtual T operator[](ptrdiff_t) = 0;
};

template<typename T>
class SpecialContainer : public AbsContainer<T>, Box<pair<ptrdiff,T>> {
    class Proxy;
public:
    Proxy operator[](ptrdiff_t i) {
        return Proxy(i, this);
    };
};

template <typename T>
class SpecialContainer<T>::Proxy  {
    ptrdiff_t _i;
    Box* _p;
public:
    Proxy(ptrdiff_t i, Box* p) : _i(i), _p(p);
    Proxy& operator=(const T& elm) {
        _p->::insert(pair<ptrdiff,T>(_i,elm));  //defined in Box
    }
};

main:

SpecialContainer<int> x;
x[2] = 3;

Это не компилируется, потому что в классе SpecialContainer, operator[] с одним в AbsContainer.

В идеале Proxy operator[] должно быть переопределением.Поэтому я попытался решить эту проблему, добившись ковариантного возвращаемого типа, заставив Proxy наследовать от T. Однако это не работает, поскольку T может быть примитивным типом, а наследование от примитивного типа не имеет смысла.

Ошибка из-законфликт операторов:

error: conflicting return type specified for ‘specialContainer<T>::Proxy B<T>::operator[](std::ptrdiff_t) [with T = int; std::ptrdiff_t = long unsigned int]

Ошибка из-за попытки наследования от параметрического типа T (в данном случае int):

error: base type ‘int’ fails to be a struct or class type

Есть ли способ решить эту проблему?

1 Ответ

0 голосов
/ 13 декабря 2018

Вы можете реализовать что-то очень похожее на ковариантные типы даже без какой-либо поддержки компилятором реальных ковариантных типов.Вот как это сделать.

#include <cstddef>
#include <map>
#include <string>
#include <iostream>

template<typename T>
class AbsContainer {
  public:
    T operator[](ptrdiff_t i) { return operator_Abs(i); }
    virtual T operator_Abs(ptrdiff_t) = 0;
};

template<typename T>
class SpecialContainer : public AbsContainer<T>, std::map<ptrdiff_t, T>  {
  public:
    class Proxy;
    Proxy operator[](ptrdiff_t i) { return operator_Spec(i); }
    T operator_Abs(ptrdiff_t i) override {
        return operator_Spec(i).get();
    }
    virtual Proxy operator_Spec(ptrdiff_t i) {
        return Proxy(i, this);
    }
};

template <typename T>
class SpecialContainer<T>::Proxy  {
    ptrdiff_t _i;
    std::map<ptrdiff_t, T>* _p;
public:
    Proxy(ptrdiff_t i, std::map<ptrdiff_t, T>* p) : _i(i), _p(p) {};
    Proxy& operator=(const T& elm) {
        _p->insert(std::pair<ptrdiff_t,T>(_i,elm));
        return *this;
    }
    T get() { return (*_p)[_i]; }
};

int main()
{
       SpecialContainer<std::string> spec;
       AbsContainer<std::string>& abs = spec;
       auto k = spec[42];
       k = "Hello World";
       std::cout << abs[42] << "\n";
}
...