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

#c #templates #explicit-instantiation

#c #шаблоны #явное создание экземпляра

Вопрос:

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

// power.h

 template <typename T>
class Power
{
public:
    T operator()(T constamp; 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: Earthn";
    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 constamp; 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> создается в другом месте?

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

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

Комментарии:

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

2. @Jarod42 Я прав в своих догадках?

Ответ №1:

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

ДА.

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

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

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

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

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

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

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

Комментарии:

1. Действительно ясный и полезный ответ, я действительно ценю это. большое вам спасибо!