cel*_*vek 44 c++ compiler-construction gcc templates visual-studio
任何人都可以提供比较或具体细节,说明在GCC和MS编译器中如何在编译和/或链接时处理模板实例化?这个过程在静态库,共享库和可执行文件的上下文中是不同的吗?我找到了关于GCC如何处理它的文档,但我不确定这些信息是否仍然指的是当前的状态.在编译我的库时,我应该使用他们建议的标志,例如-fno-implicit-templates吗?
我所知道的(可能不一定正确)是:
Seb*_*ach 56
模板将在实际使用时实例化
不完全,但粗略.实例化的确切点有点微妙,我将你委托给Vandevoorde/Josuttis的精美书中的实例化点.
但是,编译器不一定正确实现POI:错误c ++/41995:函数模板的实例化不正确
模板将在实际使用时实例化
这部分是正确的.对于函数模板也是如此,但对于类模板,只实例化使用的成员函数.以下是格式良好的代码:
#include <iostream>
template <typename> struct Foo {
    void let_me_stay() {
        this->is->valid->code. get->off->my->lawn;
    }
    void fun() { std::cout << "fun()" << std::endl; } 
};
int main () {
    Foo<void> foo;
    foo.fun();
}
let_me_stay() 语法检查(并且语法是正确的),但不是语义上的(即它不被解释).
但是,以后只解释依赖代码 ; 显然,在内Foo<>,this依赖于Foo<>实例化的确切模板ID ,因此我们推迟了Foo<>::let_me_alone()实例化时间的错误检查.
但是如果我们不使用依赖于特定实例化的东西,那么代码必须是好的.因此,以下内容并不完善:
$ cat non-dependent.cc
template <typename> struct Foo {
    void I_wont_compile() { Mine->is->valid->code. get->off->my->lawn; }
};
int main () {} // note: no single instantiation
Mine对于编译器来说,this它是一个完全未知的符号,不像编译器可以确定它的实例依赖性.
这里的关键点是C++使用两阶段查找模型,它在第一阶段检查非依赖代码,并在第二阶段(和实例化时间)完成对依赖代码的语义检查(这也是一个经常被误解或未知的概念,许多C++程序员都认为模板在实例化之前根本不会被解析,但这只是来自......,Microsoft C++的神话.
工作的定义Foo<>::let_me_stay()因为错误检查被推迟到以后,对于this指针,这是依赖的.除非你曾经使用过
显式实例化
cat > foo.cc
#include <iostream>
template <typename> struct Foo {
    void let_me_stay() { this->is->valid->code. get->off->my->lawn; }
    void fun() { std::cout << "fun()" << std::endl; } 
};
template struct Foo<void>;
int main () {
    Foo<void> foo;
    foo.fun();
}
g++ foo.cc
error: error: ‘struct Foo<void>’ has no member named ‘is’
显式实例化时,您将显式实例化.并使链接器可以看到所有符号,这也意味着模板定义可能位于不同的转换单元中:
$ cat A.cc
template <typename> struct Foo {
    void fun();  // Note: no definition
};
int main () {
    Foo<void>().fun();
}
$ cat B.cc
#include <iostream>
template <typename> struct Foo {
    void fun();
};
template <typename T>
void Foo<T>::fun() { 
    std::cout << "fun!" << std::endl;
}  // Note: definition with extern linkage
template struct Foo<void>; // explicit instantiation upon void
$ g++ A.cc B.cc
$ ./a.out
fun!
但是,您必须显式实例化所有要使用的模板参数,否则
$ cat A.cc
template <typename> struct Foo {
    void fun();  // Note: no definition
};
int main () {
    Foo<float>().fun();
}
$ g++ A.cc B.cc
undefined reference to `Foo<float>::fun()'
关于两阶段查找的小注释:编译器是否实际实现两阶段查找不受标准规定.要符合标准,但是,它应该工作,如果它没有(就像加法或乘法不一定要使用加法或乘法CPU指令来执行.
| 归档时间: | 
 | 
| 查看次数: | 9184 次 | 
| 最近记录: |