Явные специализации шаблона в cpp файле

241
22 июня 2018, 19:20

Как написать явные специализации для разных типов в другом cpp файле. На мой взгляд все писать в хедере не очень удобно и понятно. Есть шаблонный класс Array

//head.h:
template<typename Type>
class Array
{
    Type* p;
    size_t size;
    mutable int error;
    static int count;
public:
 //...
    template<typename T>
    friend std::ostream& operator<<(std::ostream&, const Array<T>&);
};
template<typename Type>
std::ostream& operator<<(std::ostream& os, const Array<Type>& a)
{
    if (a.size)
    {
        for (size_t i = 0; i < a.size; i++)
            os << a.p[i] << "  ";
    }
    return os;
}

И есть специализация для типа char (я понимаю что тут можно просто сделать приведение к типу int и не париться, но мне важен сам метод определения шаблонов):

template<>
std::ostream& operator<<(std::ostream& os, const Array<char>& a)
{
    if (a.size)
    {
        for (size_t i = 0; i < a.size; i++)
            os << int(a.p[i]) << "  ";
    }
    return os;
}

Она работает если написана в хедере, либо в main.cpp. Если я пытаюсь определить в другом cpp файле то получаю ошибки:

Ошибка  LNK2005 "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<<char>(class std::basic_ostream<char,struct std::char_traits<char> > &,class Array<char> const &)" (??$?6D@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Array@D@@@Z) уже определен в main.obj   
Ошибка  LNK1169 обнаружен многократно определенный символ - один или более  (файл arr_11.exe)   

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

Answer 1

Явная специализация шаблона функции является обычной функцией и объявляться/определяться должна по общим правилам для обычных функций.

  1. Если специализация определяет inline-функцию, то ее определение должно находиться в заголовочном файле

    template<>
    inline std::ostream& operator<<(std::ostream& os, const Array<char>& a)
    {
      ...
    }
    
  2. Если специализация определяет не-inline функцию, то в заголовочном файле должно находиться только ее объявление

    template<>
    std::ostream& operator<<(std::ostream& os, const Array<char>& a);
    

    а определение должно располагаться в одном из файлов реализации

    template<>
    std::ostream& operator<<(std::ostream& os, const Array<char>& a)
    {
      ...
    }
    
READ ALSO
работа с классами c++

работа с классами c++

у меня есть два класса TMatrix(класс для работы с матрицами) и TVector(для работы с векторами) в классе TMatrix у меня реализован метод умножения матрицы...

345
C++ tinyxml: TiXmlDocument::LoadFile(&ldquo;MyXML.xml&rdquo;) возвращает false

C++ tinyxml: TiXmlDocument::LoadFile(“MyXML.xml”) возвращает false

Не получается загрузить MyXMLxml файл, расположенный в той же директории, что и исполняемый файл приложения

176
Работа с файлами С++ (WinAPI)

Работа с файлами С++ (WinAPI)

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

351
Нахождение одного из чисел, если дан НОК двух чисел и второе число

Нахождение одного из чисел, если дан НОК двух чисел и второе число

Не могу понять, как эту задачу можно решить без "тупого" перебора чисел от НОК/данное число, до самого НОКЧисло, которое нужно найти, должно...

225