Вперед объявить функцию с параметром шаблона производного класса

Я пытался перенаправить объявление функции, которая принимает параметр шаблона, но при передаче объекта производного класса он дает мне

Error   LNK2019 unresolved external symbol 
"void __cdecl setSymetric<class Stars>(class std::vector<class Stars,class std::allocator<class Stars> > &,int,int,float,float)"
 (??$setSymetric@VStars@@@@YAXAEAV?$vector@VStars@@V?$allocator@VStars@@@std@@@std@@HHMM@Z) referenced in function 
"public: __cdecl Sector::Sector(class sf::RenderWindow &,class std::vector<class Window *,class std::allocator<class Window *> >,
class std::vector<class Image,class std::allocator<class Image> > const &)"
 (??0Sector@@QEAA@AEAVRenderWindow@sf@@V?$vector@PEAVWindow@@V?$allocator@PEAVWindow@@@std@@@std@@AEBV?$vector@VImage@@V?$allocator@VImage@@@std@@@4@@Z)        

Но когда я меняю параметр с базовым классом, он работает нормально.

Вот моя реализация функции в моем main.cpp:

template<typename A>
void setSymetric(std::vector<A>& buttons, const int startWidth,
    const int width, const float x, const float y)
{
    float substractedWidth = width - startWidth - (x * buttons.size());
    float deltaWidth = substractedWidth / (buttons.size() * 2);

    float currPos = startWidth;

    for (auto& k : buttons)
    {
        currPos += deltaWidth;

        k.getShape().setPosition(currPos, y);
        currPos += x + deltaWidth;
    }

}

Вот как я передал объявление в другом файле, где я его использую ( Sector.h это встроенный заголовок (я поместил туда свою реализацию и объявление, но я их разделю)

template<typename A>
extern void setSymetric(std::vector<A>& buttons, const int startWidth, const int width,
    const float x, const float y);

Мой базовый класс:

#ifndef IMAGES
#define IMAGES

#include<string>
#include<iostream>

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>

const std::string ImagePath = "Content/";
const std::string AudioPath = "Sound/";

extern const double width;
extern const double height;

class Image
{
public:

    Image()
    {

    }
    void play()
    {
        this->player.play();
    }

    void setTexture(const std::string& texture)
    {
        if (!this->texture.loadFromFile(ImagePath + texture))
            std::cout << "problem \n";
        shape.setTexture(&this->texture);
        shape.setSize(sf::Vector2f((width + height) / 19, (width + height) / 19));
    }

    void setTexture(const sf::Texture& texture)
    {
        this->texture = texture;
    }

    sf::Texture& getTexture()
    {
        return this->texture;
    }

    void setSound(const std::string& sound)
    {
        this->sound.loadFromFile(AudioPath + sound);
        player.setBuffer(this->sound);
    }

    sf::RectangleShape& getShape()
    {
        return this->shape;
    }

    void setVisibility(const bool flag)
    {
        this->isVisible = flag;
        if (flag == false)
        {
            this->size = this->shape.getSize();
            shape.setSize(sf::Vector2f(0, 0));
        }
        else
            shape.setSize(this->size);
    }

protected:
    sf::Texture texture;
    sf::RectangleShape shape;

    bool isVisible = true;
    sf::Vector2f size;

    sf::SoundBuffer sound;
    sf::Sound player;
};

#endif

Вот производный класс, который я передаю:

#pragma once

#include "Images.h"

class Stars : public Image
{
public:
    Stars() : Image() {

    }

    void activate() {
        this->setTexture("star.png");
    }
};

stars — двумерный массив с типом данных Stars. (Когда это изображение, оно работает) И вот как я его передаю:

setSymetric(stars[i], this->game[i].getShape().getPosition().x,
                this->game[i].getShape().getPosition().x + this->game[i].getShape().getSize().x,
                stars[i][0].getShape().getSize().x,
                this->game[i].getShape().getPosition().y + this->game[i].getShape().getSize().y);

person Ивелин Иванов    schedule 26.02.2021    source источник
comment
Осторожно: шаблоны разрешаются во время компиляции, а не во время выполнения и не во время компоновки. По этой причине шаблонные классы обычно полностью определяются во включаемых файлах. Если часть определена только в исходных файлах .c, не все версии шаблона могут быть сгенерированы, и вы получите ошибку ссылки.   -  person Serge Ballesta    schedule 26.02.2021


Ответы (1)


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

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

person Kuba hasn't forgotten Monica    schedule 26.02.2021
comment
Извините, я действительно не понял, почему я получаю сообщение об ошибке. Не могли бы вы объяснить немного больше об этом? Почему я не могу передать такой производный класс? Он работает с объектом изображения. - person Ивелин Иванов; 26.02.2021