模板是如何实例化的?

时间:2014-02-06 09:24:53

标签: c++ templates instantiation

这是 C ++ Primer 5th Edition 的练习:

  

练习16.27:对于每个带标签的陈述,解释一下,如果有的话,   实例化发生。如果模板被实例化,请解释原因;如果   不,解释为什么不。 P.677

template <typename T> class Stack { };

void f1(Stack<char>);                   // (a)

class Exercise {
    Stack<double> &rsd;                 // (b)
    Stack<int>    si;                   // (c)
};

int main() {
    Stack<char> *sc;                    // (d)
    f1(*sc);                            // (e)
    int iObj = sizeof(Stack< string >); // (f)
}

以下是我的尝试:

(a)Stack<char>被实例化,但没有实例化它的成员。

(b)Stack<double>被实例化,但没有实例化它的成员。

(c)Stack<int>及其默认构造函数被实例化。

(d)(e)完全不知道......

(f)Stack< string >被实例化,但没有实例化它的成员。

我是对的吗?谁能告诉我这个代码是如何实例化的?

2 个答案:

答案 0 :(得分:10)

在您的特定情况下,声明并不意味着实例化

#include <iostream>
using namespace std;


template <typename T> class Stack {
  typedef typename T::ThisDoesntExist StaticAssert; // T::NotExisting doesn't exist at all!
};


void f1(Stack<char>); // No instantiation, compiles

class Exercise {
  Stack<double> &rsd; // No instantiation, compiles (references don't need instantiation, are similar to pointers in this)

  Stack<int>    si; // Instantiation! Doesn't compile!!
};


int main(){

  Stack<char> *sc; // No Instantiation, this compiles successfully since a pointer doesn't need instantiation

  f1(*sc); // Instantiation of Stack<char>! Doesn't compile!!

  int iObj = sizeof(Stack< std::string >); // Instantiation of Stack<std::string>, doesn't compile!!

}

注意指针/引用的东西:它们不需要实例化,因为实际上没有分配数据(指针只包含几个字节来包含地址,不需要存储所有数据..看看pimpl idiom)。

只有在分配了东西时才需要完全解析模板(这在编译时发生,这就是为什么它们通常需要声明和定义......还没有链接阶段)< / p>

答案 1 :(得分:3)

关于e和d,我将引用标准14.7.1

  

除非已明确表示功能模板专业化   实例化或明确专门化的函数模板   专业化是在专业化时隐式实例化的   在需要函数定义存在的上下文中引用。   除非调用函数模板显式特化或者   一个显式专用类模板的成员函数,a   函数模板的默认参数或者函数的成员函数   调用函数时隐式实例化类模板   在需要默认参数值的上下文中。

示例也来自标准

template<class T> struct Z {
void f();
void g();
};

void h() 
{
Z<int> a;     // instantiation of class Z<int> required
Z<char>* p;   // instantiation of class Z<char> not required
Z<double>* q; // instantiation of class Z<double> not required
a.f();        // instantiation of Z<int>::f() required
p->g();       // instantiation of class Z<char> required, and instantiation of Z<char>::g() required
}

这意味着d中没有实例化。虽然该函数实际上需要从该类型调用函数(可以是复制构造函数或函数内部调用的任何其他函数),但它将在e中实例化。