Войти
ПрограммированиеФорумОбщее

Как вынести конструктор из декларации шаблонного класса?

Страницы: 1 2 3 Следующая »
#0
23:07, 7 сен. 2019

Не могу понять, как вынести реализацию конструктора из декларации шаблонного класса, если конструктор сам имеет шаблон с выводимым компилятором параметром:

class Object
{
public:
    template<int count>
    Object(const int(&arr)[count]);
};

template<typename T>
class TemplateObject
{
public:
    template<int count>
    TemplateObject(const int(&arr)[count]);
};

template<int count>
Object::Object(const int(&arr)[count])
{
    // ok
}

template<typename T, int count>
TemplateObject<T>::TemplateObject(const int(&arr)[count])
{
    // error C2244: 'TemplateObject<T>::TemplateObject': unable to match function definition to an existing declaration
}

int main()
{
    int a[4] = {0, 1, 2, 3};
    Object o(a);
    TemplateObject<int> to(a);
    return 0;
}

https://rextester.com/OZO78069


#1
(Правка: 23:30) 23:20, 7 сен. 2019

v1c

template<typename T>
template<int count>
TemplateObject<T>::TemplateObject(const int(&arr)[count])
{
}
#2
23:23, 7 сен. 2019

там вроде два темплейта в вынесенном методе template <typename T> template <int count>

#3
23:49, 7 сен. 2019

Funtik
Спасибо!

#4
23:49, 7 сен. 2019

#!
Спасибо!

#5
11:28, 9 сен. 2019

v1c
> как вынести реализацию конструктора из декларации шаблонного класса
никак. Темплейт должен быть реализован в том же файле, в котором объявлен

#6
11:29, 9 сен. 2019

Funtik
По идее такой код не должен скомпилиться. Так как у тебя шаблонная функция TemplateObject конфликтует с конструктором класса TemplateObject

#7
(Правка: 12:51) 12:51, 9 сен. 2019

Robotex

никак. Темплейт должен быть реализован в том же файле, в котором объявлен

кто такое сказал то?))
#8
17:39, 9 сен. 2019

oxotnik
> кто такое сказал то?
Стандарт, не?

#9
17:40, 9 сен. 2019

Невозможно написать реализацию класса шаблона в отдельном файле cpp и скомпилировать. Все способы сделать это, если кто-либо утверждает, являются обходными способами, имитирующими использование отдельного файла cpp, но практически, если вы намереваетесь написать библиотеку классов шаблонов и распространять ее с помощью файлов заголовков и lib, чтобы скрыть реализацию, это просто невозможно,

Чтобы узнать, почему, давайте посмотрим на процесс компиляции. Файлы заголовков никогда не компилируются. Они только предварительно обработаны. Затем предварительно обработанный код сгруппирован с файлом cpp, который фактически скомпилирован. Теперь, если компилятор должен создать соответствующий макет памяти для объекта, ему нужно знать тип данных класса шаблона.

На самом деле следует понимать, что класс шаблона не является классом вообще, а шаблоном для класса, объявление и определение которого генерируется компилятором во время компиляции после получения информации о типе данных из аргумента. Пока макет памяти не может быть создан, инструкции для определения метода не могут быть сгенерированы. Помните, что первым аргументом метода класса является оператор 'this'. Все методы класса преобразуются в отдельные методы с именем mangling и первым параметром в качестве объекта, на котором он работает. Аргумент 'this', который на самом деле говорит о размере объекта, который закрывает класс шаблона, недоступен для компилятора, если пользователь не создает объект с допустимым аргументом типа. В этом случае, если вы поместите определения метода в отдельный файл cpp и попытаетесь скомпилировать его, сам объект файл не будет сгенерирован с информацией о классе. Компиляция не завершится неудачей, она будет генерировать объектный файл, но он не будет генерировать код для класса шаблона в объектном файле. Именно по этой причине компоновщик не может найти символы в объектных файлах, и сборка завершилась неудачей.

Теперь, какова альтернатива скрыть важные детали реализации? Как мы все знаем, главная цель разделения интерфейса от реализации - скрывать детали реализации в двоичной форме. Здесь вы должны разделить структуры данных и алгоритмы. Ваши классы шаблонов должны представлять только структуры данных, а не алгоритмы. Это позволяет скрыть более важные детали реализации в отдельных библиотеках классов без шаблонов, классы, внутри которых будут работать классы шаблонов, или просто использовать их для хранения данных. Класс шаблона фактически будет содержать меньше кода для назначения, получения и установки данных. Остальная часть работы будет выполняться классами алгоритмов.

Я надеюсь, что это обсуждение будет полезно.

#10
19:58, 9 сен. 2019

Robotex
> если вы намереваетесь написать библиотеку классов шаблонов

А если не намереваетесь? Если я просто хочу скомпилировать реализацию инстациированного класса один раз, чтобы не пихать ее во все заголовочники, увеличить скорость компиляции и уменьшить размер бинарника? Это не модно, да?

#11
10:55, 10 сен. 2019

Robotex
Во первых: есть понятие единицы трансляции. Никаких файлов по факту нет
Во вторых: есть понятие extern и forward declaration
В третьих: Какую-то работу можно делать в линк тайм.
А ну еще SFINAE.

Ну и плюс метод к объекту очень посредственное отношение имеет.

Зная все факты, то, что написано в этом скопипащенном абзаце, бред.

ps: разработчик библиотек
pss: успешно скрываю реализацию шаблонов не в хидерах
psss: все работает и никто не жалуется

#12
12:50, 10 сен. 2019

oxotnik
твое ЧСВ меня забавляет :) Продолжай

#13
(Правка: 14:25) 13:28, 10 сен. 2019

Robotex
Меня забавляют люди, говорящие, что "Невозможно написать реализацию класса шаблона в отдельном файле cpp и скомпилировать"

Или в принципе говорящие, что что-то там нельзя сделать.

При это незнающие плюсы.

В чем смысл

¯\_(ツ)_/¯

ps: я из-за таких вот людей в свое время думал, что многие вещи в плюсах нельзя сделать.

#14
14:01, 10 сен. 2019

Тут никто не путает реализацию со специализацией?

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумОбщее