Специализация шаблонов и общий код

86
21 апреля 2021, 02:00

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

template <typename CMD>
class Version
{
public:
    Version(ByteVector &byteVector) : byteVector(byteVector) {};
    Object<DATA<CMD>>   cls_DATA();
    Object<USR<CMD>>    cls_USR();
    Object<AUTH<CMD>>   cls_AUTH();
    Object<CONN<CMD>>   cls_CONN();
private:
    ByteVector &byteVector;
};

И реализация метода cls_AUTH() в том же .h-файле

template<typename CMD>
inline Object<AUTH<CMD>> Version<CMD>::cls_AUTH()
{
    return Object<AUTH<CMD>>(byteVector);
}

В том же файле есть специализация с отличием в том, что в этой версии доступен только один метод

template <>
class Version<AOPEN>
{
public:
    Version(ByteVector &byteVector) : byteVector(byteVector) {};
    Object<AUTH<AOPEN>> cls_AUTH();
private:
    ByteVector &byteVector;
};

Так вот при использовании этого метода в специализации выходит unresolved external symbol. А при попытке определить метод второй раз, для специализации первая ошибка остаётся, и появляется вторая - not an entity that can be explicitly specialized в специализированном определении этого метода.

Answer 1

Два класса — два определения. Нельзя определить функцию только для одного класса и использовать это определение для объявлений в разных классах. Поэтому, чтобы использовать одну реализацию в разных классах нужно либо использовать наследование, либо свободные функции, либо композицию. При наследовании, думаю, что всё и так понятно. Решение со свободной функцией будет выглядеть как-то так:

template<typename CMD>
Object<AUTH<CMD>> cls_AUTH(ByteVector& byteVector)
{
    return Object<AUTH<CMD>>(byteVector);
}
template <typename CMD>
class Version
{
    //..
    Object<DATA<CMD>> cls_AUTH()
    {
        return cls_AUTH<CMD>(byteVector);
    }
    //..
private:
    ByteVector &byteVector;
};
template <>
class Version<AOPEN>
{
    //..
    Object<AUTH<AOPEN>> cls_AUTH()
    {
        return cls_AUTH<AOPEN>(byteVector);
    }
private:
    ByteVector &byteVector;
};

С композицией будет то же самое, просто функции будут принадлежать какому-то классу, а в Ваших классах будет объект этого класса, но суть от этого не меняется.

P.S. наследование будет проще всего, т.к. будет гораздо меньше писанины.

Answer 2

Нужно переопределить метод, но не так:

template<>
inline Object<AUTH<AOPEN>> Version<AOPEN>::cls_AUTH()
{
    return Object<AUTH<AOPEN>>(byteVector);
}

а без template<> в начале. Т. е. чтобы было просто:

inline Object<AUTH<AOPEN>> Version<AOPEN>::cls_AUTH()
{
    return Object<AUTH<AOPEN>>(byteVector);
}
READ ALSO
Проблема с записью в массив Jquery [закрыт]

Проблема с записью в массив Jquery [закрыт]

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском

108
Как скрыть тег html таблицы по itemprop

Как скрыть тег html таблицы по itemprop

Как можно скрыть первую строку в таблице, если таблица для товара создается автоматически в админкеПробовал через js (сам новичок в этом),...

108
Как проверить открыто ли окно в WPF?

Как проверить открыто ли окно в WPF?

Как проверить открыто ли окно в WPF? Когда окно открыто, то при нажатии на кнопу открывается новое окноКак предотвратить это?

122
Как сохранить данные в txt datagridview c каждой TabPages

Как сохранить данные в txt datagridview c каждой TabPages

Есть программа имеющая 16 одинаковых вкладок с разным содержанием DatagridView(их тоже 16шт) на каждой из них

116