如果一个函数定义有一个 class 模板类型的参数并且没有使用它(它的成员)那么它是否被实例化?
If a function definition has a parameter of class template type and didn't use it (its members) then is it instantiated?
从我在此处发布的关于 的先前示例中,我得到的答案是只有在使用模板时,编译器才会实例化它。但是看看这个例子:
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;
}
如您所见,我已经声明了一个显式模板实例化 Pow<int>
但还没有定义它。该程序运行良好,不会抱怨缺少 Pow<int>
!
的定义
在上一个主题中,如果我使用模板类型作为函数定义(而不是声明)的参数类型,那么模板将被实例化,但如您所见,我在此处得到了回答:定义了成员函数Foo::fn(Pow<int>)
和普通函数函数bar(Pow<int>)
但是编译器没有报错Pow<int>
的定义?!!!
如果我取消注释上述函数中的行,程序将无法编译。那么这是否意味着 Pow<int>
在用作函数定义中的函数参数和用作 Foo::Pow<int> pi{};
中的成员数据时未实例化?
我觉得很困惑:
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?
主要内容:
Foo f; // f has pi of type Pow<int>. so Pow<int> is instantiated?
Pow<int>
是定义的。它被定义为 Pow<T>
和 T=int
。
The program works just fine and doesn't complain about the missing definition of Pow<int>
!
因为它没有丢失。两种形式的显式实例化(声明和定义)都会导致 class 模板的实例化。显式实例化定义会导致成员函数的实例化(通常仅在需要时才延迟实例化)。另一方面,显式实例化声明将抑制成员函数的隐式实例化。即使那个成员函数体是可见的!
它是一种为一组受限类型编写模板,同时隐藏其实现的工具。它允许人们这样做:
//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.
这正是您的程序无法 link 的原因。成员 operator()
永远不会在您的程序中的任何地方实例化。您可以通过在某处提供显式实例化定义来修复它。例如
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
它的另一个用途是潜在地缩短编译时间。如果您有 知道 的 class 模板经常针对一组特定的类型进行实例化,您可以帮助 link 人员。
// 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>;
现在 link 用户不必对常用 my_string<char>
和 my_string<wchar_t>
.[=18 的隐式实例化产生的许多重复符号进行排序=]
从我在此处发布的关于
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;
}
如您所见,我已经声明了一个显式模板实例化
的定义Pow<int>
但还没有定义它。该程序运行良好,不会抱怨缺少Pow<int>
!在上一个主题中,如果我使用模板类型作为函数定义(而不是声明)的参数类型,那么模板将被实例化,但如您所见,我在此处得到了回答:定义了成员函数
Foo::fn(Pow<int>)
和普通函数函数bar(Pow<int>)
但是编译器没有报错Pow<int>
的定义?!!!如果我取消注释上述函数中的行,程序将无法编译。那么这是否意味着
Pow<int>
在用作函数定义中的函数参数和用作Foo::Pow<int> pi{};
中的成员数据时未实例化?我觉得很困惑:
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?
主要内容:
Foo f; // f has pi of type Pow<int>. so Pow<int> is instantiated?
Pow<int>
是定义的。它被定义为 Pow<T>
和 T=int
。
The program works just fine and doesn't complain about the missing definition of
Pow<int>
!
因为它没有丢失。两种形式的显式实例化(声明和定义)都会导致 class 模板的实例化。显式实例化定义会导致成员函数的实例化(通常仅在需要时才延迟实例化)。另一方面,显式实例化声明将抑制成员函数的隐式实例化。即使那个成员函数体是可见的!
它是一种为一组受限类型编写模板,同时隐藏其实现的工具。它允许人们这样做:
//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.
这正是您的程序无法 link 的原因。成员 operator()
永远不会在您的程序中的任何地方实例化。您可以通过在某处提供显式实例化定义来修复它。例如
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
它的另一个用途是潜在地缩短编译时间。如果您有 知道 的 class 模板经常针对一组特定的类型进行实例化,您可以帮助 link 人员。
// 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>;
现在 link 用户不必对常用 my_string<char>
和 my_string<wchar_t>
.[=18 的隐式实例化产生的许多重复符号进行排序=]