2011-11-02 90 views
6

你好,祝你有美好的一天。C++:强制完成模板编译(MSVC/G ++)

下面的代码片段在编译的cl.exe(15.00.30729.01)和MinGW-G ++(4.4.0):

template<typename T> class Test{ 
public: 
    T t; 
    void error(){ 
     int doesNotExist = 6; 
     return doesNotExist;//<---- void function returning result 
    } 
}; 

int main(int argc, char** argv){ 
    Test<int> test; 
    return 0; 
} 

此外,在cl.exe时你甚至可以像这样脱身:

template<typename T> class Test{ 
public: 
    T t; 
    void error(){ 
     doesNotExist = 6;//<---- undeclared variable 
     return doesNotExist;//<---- void function returning result 
    } 
}; 

现在,这显然发生,因为编译器不会创建模板类的方法的内容,直到有人调用它们。但是,当您设计大型模板类时,这可能会造成问题(因为您很可能忘记将测试调用添加到新方法的某处)。

的问题是:
是否有g的编译器开关++或cl.exe时,这将迫使编译器来处理整个模板(因此,此代码片段将触发编译错误)?

回答

11

如果你想与几个类型的测试模板,您可以触发类型的手动实例,如:类模板

// at namespace level 
template class Test<int>; 

显式实例自动触发所有成员的实例,其似乎是你想要的。

实际的问题是,该语言旨在明确允许您想避免的行为。当一个类模板被隐式实例化时,编译器将只实例化那些使用的方法。该特性的主要用例是某些方法可能对实例化类型施加比其他方法更严格的要求,如果所有方法都实例化了总是那么类模板只能用于那些满足更严格要求的类型。

通过允许编译器仅实例化那些使用的方法,类模板可以与不满足所有方法的所有要求的类型一起使用,只要它们满足方法的要求这是实际使用的。

一个常见的例子是在std::map<>operator[]需要的value_type默认constructibleoperator[]将创建一个新对象缺省初始化如果该键不存在在容器中,并返回对它的引用)。只要您不使用operator[](或任何其他强制实施该要求的成员函数),该语言的行为允许您在不是默认构造的的类型上使用std::map

+2

是的,显式模板实例化是你想要的。另请参阅:http://msdn.microsoft.com/en-us/library/by56e477%28VS.80%29.aspx –

+0

对于没有编译器错误的实际目的很好的解释。 – iammilind

+0

好的,它的工作原理。我接受你的回答,但没有必要解释为什么这种方式有效(我已经知道)。谢谢回复。 – SigTerm