模板错误 我听说C++模板在使用之前不会产生错误。这是真的吗?有人能给我解释一下它们是如何工作的吗

模板错误 我听说C++模板在使用之前不会产生错误。这是真的吗?有人能给我解释一下它们是如何工作的吗,c++,templates,C++,Templates,从 编译器,模板不正常 函数或类。他们是 按需编译,意味着 模板函数的代码不可用 编译,直到使用 特定的模板参数是 必修的。在那一刻,当 需要实例化, 编译器生成一个函数 专门针对来自 模板 希望对您有所帮助。他们在编译时会生成编译器错误。它们分别针对作为模板参数传递的每个实际参数进行编译(这与Java泛型不同),例如,如果我有: template <typename T> class foo { ... } 模板类foo{…} 及 intmain(){ 富科; 富一; } 模

从 编译器,模板不正常 函数或类。他们是 按需编译,意味着 模板函数的代码不可用 编译,直到使用 特定的模板参数是 必修的。在那一刻,当 需要实例化, 编译器生成一个函数 专门针对来自 模板

希望对您有所帮助。

他们在编译时会生成编译器错误。它们分别针对作为模板参数传递的每个实际参数进行编译(这与Java泛型不同),例如,如果我有:

template <typename T> class foo { ... }
模板类foo{…}

intmain(){
富科;
富一;
}
模板
foo
编译两次,一次用于chars,一次用于int

如果您从未(直接或间接)实例化或使用模板
foo
,它将不会被编译,也不会看到任何编译器错误


编译后,它们只是“普通”C++代码,和任何代码一样,都会产生运行时错误。

模板遵循两阶段编译模型。

struct X{
private:
   void f(){}
};

template<class T> void f(T t){
   int;   // gives error in phase 1 (even if f(x) call is commented in main)
   t.f(); // gives error only when instantiated with T = X, as x.f() is private, in phase 2
}

int main(){
   X x;
   f(x);
}
struct X{
私人:
void f(){}
};
模板空隙f(T){
int;//在阶段1中给出错误(即使f(x)调用在main中被注释)
t、 f();//仅当使用t=X进行实例化时才给出错误,因为在阶段2中,X.f()是私有的
}
int main(){
X;
f(x);
}

概念上,在最高级别

template <Type value, class Y, ...> ...fn-or-class... 模板 …fn或类。。。 可以与

#define FN_OR_CLASS(VALUE, TYPE_Y, ...) \ ...fn-or-class... #定义FN_或_类(值、类型_Y,…)\ …fn或类。。。 这两种方法基本上都是等待调用/实例化,然后替换指定的类型和值来生成定制代码,并对这些值进行完整的编译时优化。但是,模板与#定义的不同之处在于,它们是适当的编译阶段构造,可以包含在名称空间中,必须满足lexer,并且在看到第一个实例化时,并不是所有类模板都生成,而是根据需要生成函数

当编译器第一次遇到模板时,它会粗略地检查模板的内容是否对某些假设的实例化有意义。稍后,当遇到特定的实例化时,对于类模板,只会进一步检查所使用的函数,以确保它们可以使用使用的特定参数进行编译。这确实意味着类模板可能会出现(对于某些有限的用途)以支持使用特定参数的实例化,但是如果您开始在模板API中使用其他一些函数,那么您会突然发现无法使用假定的合适参数编译它。。。这会迫使你在一天中很晚的时候重新设计你的用法。这就是C++0x计划引入概念的原因之一:它们优雅地允许模板检查参数是否满足模板的所有期望值——如果它们允许任何实例化,那么用户可以假设可以使用模板的完整API

template <class T> struct X { void f() { } void g() { T::whatever(); } // only error if g() called w/o T::whatever }; int main() { X<int> x; x.f(); // x.g(); // would cause an error as int::whatever() doesn't exist... } 模板 结构X { void f(){} void g(){T::whater();}//只有当g()调用w/o T::whater时才出现错误 }; int main() { X; x、 f(); //x.g();//将导致错误,因为int::whater()不存在。。。 }
然后,SFINAE(替换失败不是错误)技术允许编译器根据实际的实例化模板参数在多个几乎匹配的函数之间进行选择。这可用于实现基本的编译时自省,例如“该类是否具有成员函数fn(int)?”

在模板类的一般术语中,这意味着编译器将为声明的每种类型的模板类生成不同的类型。因此
向量
向量
不同。如果你没有声明任何
vector
类型,那么就不会生成任何类型。@Duracell,是的,我同意,这就是,编译器专门为这些参数生成一个函数…这仍然不允许语法无效的代码在第一次传递时出现错误。部分混淆可能来自这样一个事实,VC++跳过了第一次传递,所以只要模板没有实例化,就可以在模板中放入任何乱七八糟的内容。Georg,该标准是否要求第一次通过?@tpdi:是的,VC++不符合要求。@tpdi:请参阅以上答案的注释;标准描述了此类检查,但明确指出它们不会影响法规遵从性。实际上,标准要求模板遵循两阶段编译模型,但有些编译器(最明显的是VS)不这样做,因此只在第二阶段发出警告/错误(除非情况非常糟糕,以致解析器阻塞)@ Mattieu和CubsDaDe:在这个标准中有什么特殊的地方吗?请参考David Vandervoorde的C++模板10.3节。第14.6节实际上间接地谈到了这个概念。e、 g.“[注:如果模板被实例化,则将根据本标准中的其他规则诊断错误。准确诊断这些错误的时间是实现质量问题。]”@Matthieu and chubsdad:找到了它。14.6/7:“如果无法为模板定义生成有效的专门化,且该模板未实例化,则模板定义格式错误,无需诊断。”因此,这根本不是合规性问题。该标准强烈建议进行此类检查,并声明此类支持提高了“实现质量”,但也明确了不需要对非实例化模板进行诊断。对于C++0x,段落没有更改。我发现一些文章有相反的观点,但引用不好;我会称之为FUD。@chubsdad:如果标准没有直接谈论某些东西,它就不在那里。”…它会粗略检查模板是否正确 template <class T> struct X { void f() { } void g() { T::whatever(); } // only error if g() called w/o T::whatever }; int main() { X<int> x; x.f(); // x.g(); // would cause an error as int::whatever() doesn't exist... }