如果一个函数定义有一个 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<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 的隐式实例化产生的许多重复符号进行排序=]