[英]If a function definition has a parameter of class template type and didn't use it (its members) then is it instantiated?
From the previous example I've posted here about when the template
is instantiated?从上一个示例中,我在这里发布了有关何时实例化
template
的信息? , I got the answer that only when a template is used the compiler instantiates it. ,我得到的答案是,只有在使用模板时,编译器才会实例化它。 But look at this example:
但是看看这个例子:
template <typename T>
struct Pow{
T operator()(T const& x){ return x * x; }
};
extern template struct Pow<int>; // explicit instantiation declaration
struct Foo{
Pow<int> pi{};
void fn(Pow<int>);
};
void Foo::fn(Pow<int> pw){
// std::cout << pw(7) << '\n';
}
void bar(Pow<int> pwi){
// std::cout << pwi(10) << '\n';
}
int main(){
Foo f;
}
As you can see I've declared an explicit template instantiation Pow<int>
but haven't defined it.如您所见,我已经声明了一个显式模板实例化
Pow<int>
但尚未定义它。 The program works just fine and doesn't complain about the missing definition of Pow<int>
!该程序运行良好,并且不会抱怨缺少
Pow<int>
定义!
In the previous topic I've been answered if I use a template type as a type of parameter for a function definition (not declaration) then the template is instantiated but here as you can see: The member function Foo::fn(Pow<int>)
and the ordinary function function bar(Pow<int>)
are defined but the compiler doesn't complain about the definition of Pow<int>
?!!!在上一个主题中,如果我使用模板类型作为函数定义(不是声明)的参数类型,那么模板将被实例化,但在这里您可以看到:成员函数
Foo::fn(Pow<int>)
和普通函数函数bar(Pow<int>)
被定义了但是编译器没有抱怨Pow<int>
的定义?!!!
The program fails to compile if I un-comment the lines in the aforementioned functions.如果我取消注释上述函数中的行,程序将无法编译。 so does it mean that
Pow<int>
is not instantiated when used as function parameter in the function definition and as member data like in Foo::Pow<int> pi{};
这是否意味着
Pow<int>
在用作函数定义中的函数参数和像Foo::Pow<int> pi{};
成员数据时不会被实例化Foo::Pow<int> pi{};
? ?
I find it confusing:我觉得很困惑:
void f(Pow<int>); // function declaration: Pow<int> is not instantiated yet. void f2(Pow<int>){} // function definition: Pow<int> instantiated? void f3(pow<int> Pwi){ std::cout << Pwi(10);} // function definition and usage of `Pow<int>`: Pow<int> instantiated?
In main:在主要:
Foo f; // f has pi of type Pow<int>. so Pow<int> is instantiated?
Pow<int>
is defined. Pow<int>
已定义。 It is defined as Pow<T>
with T=int
.它被定义为
Pow<T>
和T=int
。
The program works just fine and doesn't complain about the missing definition of
Pow<int>
!该程序运行良好,并且不会抱怨缺少
Pow<int>
定义!
Because it isn't missing.因为它不缺。 Both forms of explicit instantiation (declaration and definition) cause the instantiation of class templates.
显式实例化的两种形式(声明和定义)都会导致类模板的实例化。 An explicit instantiation definition causes the instantiation of member functions (which are normally instantiated lazily only when needed).
显式实例化定义会导致成员函数的实例化(通常仅在需要时才延迟实例化)。 On the other hand, an explicit instantiation declaration will suppress the implicit instantiation of a member function.
另一方面,显式实例化声明将抑制成员函数的隐式实例化。 Even if that member function body is visible!
即使那个成员函数体是可见的!
It's a tool to write templates for a constrained set of types, while hiding their implementation.它是一种为一组受约束的类型编写模板的工具,同时隐藏它们的实现。 It allows one to do this:
它允许一个人这样做:
//pow.h
template <typename T>
struct Pow{
T operator()(T const& x); // Just a declaration
};
extern template struct Pow<int>; // The class is instantiated, the member is
// assumed to be explicitly instantiated elsewhere
//pow.cpp
#include "pow.h"
template <typename T>
T Pow<T>::operator()(T const& x) { return x * x; }
template struct Pow<int>; // Explicit instantiation. The member function is defined
// in **this** translation unit.
And that is exactly why your program fails to link.这正是您的程序无法链接的原因。 The member
operator()
is never instantiated anywhere in your program.成员
operator()
永远不会在您的程序中的任何地方实例化。 You can fix it by providing an explicit instantiation definition somewhere.您可以通过在某处提供显式实例化定义来修复它。 For instance
例如
template <typename T>
struct Pow{
T operator()(T const& x){ return x * x; }
};
// ...
int main() {
// ...
}
template struct Pow<int>; // Now the member function is emitted
Another use of this can be to potentially improve compile times.另一个用途是潜在地改进编译时间。 If you have a class template that you know is often instantiated for a specific set of types, you can help the linker along.
如果你有一个类模板,你知道通常实例化一组特定的类型,可以帮助沿着连接器。
// my_string.h
template<typename charT>
class my_string {
// Everything, members and all
};
extern template class my_string<char>;
extern template class my_string<wchar_t>;
// my_string.cpp
#include <my_string.h>
// This file can be part of a shared object that ships with your library
// The common declarations are here
template class my_string<char>;
template class my_string<wchar_t>;
Now the linker doesn't have to sort the many duplicate symbols that would have been produced by implicit instantiation of the commonly used my_string<char>
and my_string<wchar_t>
.现在,链接器不必对由常用
my_string<char>
和my_string<wchar_t>
的隐式实例化产生的许多重复符号进行排序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.