C++ ковариантные шаблоны

Насколько вы точны? Если вам нужно учитывать общие годы и високосные годы и точную разницу в днях между месяцами, тогда вам придется написать что-то более продвинутое, но для базового и грубого расчета это должно сделать трюк:

today = new Date()
past = new Date(2010,05,01) // remember this is equivalent to 06 01 2010
//dates in js are counted from 0, so 05 is june

function calcDate(date1,date2) {
    var diff = Math.floor(date1.getTime() - date2.getTime());
    var day = 1000 * 60 * 60 * 24;

    var days = Math.floor(diff/day);
    var months = Math.floor(days/31);
    var years = Math.floor(months/12);

    var message = date2.toDateString();
    message += " was "
    message += days + " days " 
    message += months + " months "
    message += years + " years ago \n"

    return message
    }


a = calcDate(today,past)
console.log(a) // returns Tue Jun 01 2010 was 1143 days 36 months 3 years ago

Имейте в виду, что это неточно, для того, чтобы рассчитать дату с полной точностью, нужно было бы иметь календарь и знать, год ли високосный год или нет, также как я рассчитываю номер месяцев является приблизительным.

Но вы можете легко его улучшить.

17
задан rmeador 12 March 2009 в 15:46
поделиться

6 ответов

И конструктор копии и оператор присваивания должны быть в состоянии взять SmartPtr другого типа и попытки скопировать указатель от одного до другого. Если типы не будут совместимы, то компилятор будет жаловаться, и если они совместимы, Вы решили свою проблему. Что-то вроде этого:

template<class Type> class SmartPtr
{
    ....
    template<class OtherType> SmartPtr(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> copy constructor

    template<class OtherType> SmartPtr<Type> &operator=(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> assignment operator
};
12
ответ дан 30 November 2019 в 11:44
поделиться

SmartPtr<Base> и SmartPtr<Derived> два отличных инстанцирования эти SmartPtr шаблон. Эти новые классы не совместно используют наследование, которые Base и Derived делают. Следовательно, Ваша проблема.

, что лучший способ состоит в том, чтобы выполнить эту операцию присвоения?

 SmartPtr<Base> b = d; 

не вызывает оператор присваивания. Это вызывает копию-ctor (копия игнорируется в большинстве случаев), и точно, как будто Вы записали:

 SmartPtr<Base> b(d); 

Предусматривают копию-ctor, которая берет SmartPtr<OtherType>, и реализуйте ее. То же идет для оператора присваивания. Необходимо будет выписать копию-ctor и op = учет семантики SmartPtr.

15
ответ дан 30 November 2019 в 11:44
поделиться

Шаблоны не являются ковариантными, и это хорошо; вообразите то, что произошло бы в следующем случае:

vector<Apple*> va;
va.push_back(new Apple);

// Now, if templates were covariants, a vector<Apple*> could be
// cast to a vector<Fruit*>
vector<Fruit*> & vf = va;
vf.push_back(new Orange); // Bam, we just added an Orange among the Apples!

Для достижения, что Вы пытаетесь сделать класс SmartPointer должен иметь templatized конструктора, который берет или другой SmartPointer или указатель другого типа. Вы могли взглянуть на повышение:: shared_ptr, который делает точно это.

template <typename T>
class SmartPointer {

    T * ptr;

  public:
    SmartPointer(T * p) : ptr(p) {}
    SmartPointer(const SmartPointer & sp) : ptr(sp.ptr) {}

    template <typename U>
    SmartPointer(U * p) : ptr(p) {}

    template <typename U>
    SmartPointer(const SmartPointer<U> & sp) : ptr(sp.ptr) {}

    // Do the same for operator= (even though it's not used in your example)
};
5
ответ дан 30 November 2019 в 11:44
поделиться

Зависит от SmartPtr класс. Если это имеет конструктора копии (или в Вашем случае, операторе присваивания), который берет SmartPtr<T>, где T является типом, это было создано с, то это не собирается работать, потому что SmartPtr<T1> не связано с SmartPtr<T2>, даже если T1 и T2 связаны наследованием.

Однако, если SmartPtr имеет конструктор/оператор присваивания копии templatized с шаблонным параметром TOther, который принимает SmartPtr<TOther>, тогда это должно работать.

3
ответ дан 30 November 2019 в 11:44
поделиться

Принятие Вас имеет контроль над классом SmartPtr, решение состоит в том, чтобы предоставить шаблонному конструктору:

template <class T>
class SmartPtr
{
    T *ptr;
public:

    // Note that this IS NOT a copy constructor, just another constructor that takes 
    // a similar looking class.
    template <class O>
    SmartPtr(const SmartPtr<O> &src)
    {
        ptr = src.GetPtr();
    }
    // And likewise with assignment operator.
};

, Если типы T и O совместимы, это будет работать, если они не будут, Вы получите ошибку компиляции.

2
ответ дан 30 November 2019 в 11:44
поделиться

Я думаю, что самая легкая вещь состоит в том, чтобы обеспечить автоматическое преобразование в другой SmartPtr согласно следующему:

template <class T>
class SmartPtr
{
public:
    SmartPtr(T *ptr) { t = ptr; }
    operator T * () const { return t; }
    template <class Q> operator SmartPtr<Q> () const
    { return SmartPtr<Q>(static_cast<Q *>(static_cast<T *>(* this))); }
private:
    T *t;
};

Примечание, что эта реализация устойчива в том смысле, что шаблон оператора преобразования не должен знать о семантике интеллектуального указателя, таким образом, для подсчета ссылок не нужно к дублируемому и т.д.

0
ответ дан 30 November 2019 в 11:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: