Как работает явное создание экземпляра шаблона?

Я изо всех сил пытаюсь понять явное создание шаблона с использованием спецификатора extern. Вот мой пример

// power.h

template <typename T>
class Power
{
public:
    T operator()(T const& x) {return x * x;}
};

// power.cpp

#include "power.h"

template
class Power<int>;

//mathlib.h

class Square
{
public:
    Square(int);
    inline int side()const { return side_;}
    int surface()const;
    int perim()const;

private:
    int side_{};
};

// mathlib.cpp

#include "mathlib.h"
#include "power.h"

extern template class Power<int>;

Square::Square(int x) :
    side_(x)
{}

int Square::surface() const
{
    return Power<int>{}(side_);
}

int Square::perim() const
{
    return side_ * 4;
}

//physiqlib.h

class Planet
{
public:
    Planet(int);
    int velocity()const;

private:
    int veloc_{};
};

//physiqlib.cpp

#include "physiqlib.h"
#include "power.h"

extern template class Power<int>;


Planet::Planet(int v) :
    veloc_(v)
{}

int Planet::velocity()const
{
    return Power<int>{}(veloc_);
}

//main.cpp

#include <iostream>
#include "mathlib.h"
#include "physiqlib.h"
#include "power.h"

int main()
{

    Square sq{7};
    std::cout << "side: " << sq.side() << '\n';
    std::cout << "surface: " << sq.surface() << '\n';
    std::cout << "perim: " << sq.perim() << '\n';

    std::cout << '\n';
    std::cout << "Planet name: Earth\n";
    Planet plEarth(150000);
    std::cout << "velocity: " << plEarth.velocity() << '\n';

    std::cout << "\ndone!\n";
}
  • Когда я компилирую программу, она работает нормально и дает правильные результаты, однако я хочу знать, работает ли это Explicit instantiation так или нет?

  • Мне очень жаль, что я написал всю свою программу, но я пытаюсь только показать, как я ее использую.

  • Я также привожу это в качестве произвольного примера и для краткости снимаю здесь ограничители включения из заголовков.

  • Пожалуйста, объясните, нахожусь ли я на правильном пути, особенно я сделал поиск по форуму, и я все еще немного запутался.

** Если я компилирую программу из терминала, генерирующего промежуточные файлы: g++ -S -save-temps main.cpp physiqlib.cpp power.cpp mathlib.cpp Почему я получаю в каждом *.ii определение класса шаблона Power? что-то вроде этого:

// mathlib.ii

# 1 "mathlib.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "mathlib.cpp"
# 1 "mathlib.h" 1
    

class Square
{
public:
    Square(int);
    inline int side()const { return side_;}
    int surface()const;
    int perim()const;

private:
    int side_{};
};
# 2 "mathlib.cpp" 2
# 1 "power.h" 1



template <typename T>
class Power
{
public:
    T operator()(T const& x) {return x * x;}
};
# 3 "mathlib.cpp" 2

extern template class Power<int>;

Square::Square(int x) :
    side_(x)
{}

int Square::surface() const
{
    return Power<int>{}(side_);
}

int Square::perim() const
{
    return side_ * 4;
}
  • Означает ли это, что шаблон класса Power только определен, но еще не создан, а экземпляр class Power<int> находится где-то еще?

  • Если я прав, доступен ли этот метод в соответствии с новым стандартом, чтобы избежать раздувания кода шаблона?

Большое спасибо!


person Maestro    schedule 10.11.2020    source источник
comment
*.ii - это файл после предварительной обработки, не связанный с созданием экземпляра шаблона.   -  person Jarod42    schedule 11.11.2020
comment
@ Jarod42 Верно ли я в своих догадках?   -  person Maestro    schedule 11.11.2020


Ответы (1)


Я хочу знать, так ли работает явное создание экземпляра?

да.

Почему я добавляю в каждый * .ii определение шаблона класса Power?

Файлы * .ii являются результатом предварительной обработки. не имеет отношения к созданию экземпляра шаблона.

Означает ли это, что шаблон класса Power только определен, но еще не создан, а экземпляр класса Power находится где-то еще?

Да, неявное создание экземпляра не выполняется с помощью вызова return Power<int>{}(side_);

Если я прав, доступен ли этот метод в соответствии с новым стандартом, чтобы избежать раздувания кода шаблона?

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

Подробнее о class_template # Explicit_instantiation

person Jarod42    schedule 11.11.2020
comment
Действительно ясный и полезный ответ, я ценю это. большое спасибо! - person Maestro; 11.11.2020