当前位置:首页 » 编程软件 » 模板编译期替换

模板编译期替换

发布时间: 2022-05-29 07:32:12

‘壹’ Vue 模板编译 是用来代替JSP的吗

JSP可以和Vue一起使用,但vue本身更倾向于基于node的服务端渲染SSR

‘贰’ c++primer3中,有一句话:“在多个文件之间编译相同的函数模板定义增加了不必要的编译时间”……

简单点说,对于一个vector<int>的函数,比如size(),如果在不同的cpp中出现,在这些文件编译的时候都要把vector<int>::size()编译一遍。然后在链接的时候把重复的函数去掉。很显然增加了编译时间。

补充里你的理解是错的,模板的声明是不编译的,更没有空间,它根本不是实际的类型或函数,编译器根本不管它。只有实例化的时候,才生成真正的类型、函数,而实例化的地方不在一起,必然造成同一个类型、函数被编译了多次。反观类的编译,只在它的cpp中编译一次,其他地方都使用它的头文件得到声明。

‘叁’ c++函数模板替代函数编写

一楼的很有意思,你这篇文章其实是很经典的,但与本问题无关...

问题在这一句:

string e = myfunc("aa", "bbb");

编译器已经很明确地告诉你了,不能把2个指针相加,因为在用双引号括起来的字符都是所谓的C风格字符串,即以一个指针来标明其首个字符并以'/0'作为结束信号的字符串,比如:

const char* p = "hello, world!";

如果你将其打出,如:

cout << p;

则指针p便会把其指向的字符逐个打印出来,再遇到'\0'时结束。

在你的问题中,由于"aa"和"bbb"无法被转化为string类,所以编译器不会调用这个函数:

string myfunc(string a, string b)
{
string c = a + b;
return c;
}

而是为它们生成了特定的模版:

char* myfunc(char* a, char* b);

由于两个指针的相加是没有被定义的,所以编译器报错。

由于string e = myfunc("aa", "bbb")中的"aa"和"bbb"被默认作为了C风格的字符串,而编译器没有定义一种隐式的转换方法可以把C风格字符串转化为string类,所以你必须通过显式地把它们转换为string类字符串,可以这样:

string e = myfunc(string("aa"),string("bbb"));

或者用更加一目了然且安全但烦琐而冗长的C++式cast句法:

string e = myfunc(static_cast<string>("aa"), static_cast<string>("bbb"));

另外说下用了模版的话你的这个函数就可以砍掉了:

string myfunc(string a, string b)
{
string c = a + b;
return c;
}

另外如果你不想烦琐地每次调用myfunc来实现2个字符的相加都要通过cast的话也可以把myfunc模板实例化:

#include <iostream>
#include <string>
#include <cmath>
#include <cstring>
using namespace std;

template<class T>
T myfunc(T a,T b){
T c=a+b;
return c;
}
// 模板实例化
template<> const char* myfunc<const char*>(const char* a, const char* b)
{
string temp = string(a) + string(b);
return temp.c_str(); // 结果可能出乎你的预料~
}

// 或者

// 模板实例化
/* template<> const char* myfunc<const char*>(const char* a, const char* b)
{
char* pa = new char[sizeof a + sizeof b];
const char* pc = strcat(strcpy(pa, a), b);
delete [] pa;

return pc; // 同上
}*/

int main(){
int c;
float d;
c=myfunc(3,4);
cout<<c<<endl;
d=myfunc(3.4,4.7);
cout<<d<<endl;
string e=myfunc("aa","bbb");
cout<<e<<endl;
system("pause");
return 0;
}

你运行这个程序得到的e可能是乱码,原因可见一楼的部分提示:

8. 不要再写 char* p = "XXX" 这种语句,要写成 const char* p = "XXX",编译器之所以让前者通过编译是为了兼容以前的大量的旧代码。
BTW:const TYPE* p 和 TYPE const* p 是一样的,风格不同而已。
BTW:C语言中也有const关键字。

详细可见:

http://community.csdn.net/Expert/TopicView3.asp?id=5085350

‘肆’ 请教C++模板函数在编译时处理

模板函数类型检查是放在调用的时候检查的.因为在定义的时候是没有办法区分的(比如你这个例子,就存在int转换float和float转换int的警告级别差异.)

所以严格的说来,编译器是发现调用了test(v1,u1),才开始检查的.由于底层实现将形参类型用实际V1和u1的类型做了替换,然后就可以实际判断隐式转换的合理性.

‘伍’ 为什么C++编译器不能支持对模板的分离式编译

当编译器将一个工程里的所有.cpp文件以分离的方式编译完毕后,再由连接器(linker)进行连接成为一个.exe文件。 举个例子: //---------------test.h-------------------//void f();//这里声明一个函数f //---------------test.cpp--------------//#include”test.h”void f(){…//do something} //这里实现出test.h中声明的f函数 //---------------main.cpp--------------//#include”test.h”int main(){f(); //调用f,f具有外部连接类型} 在这个例子中,test. cpp和main.cpp各自被编译成不同的.obj文件(姑且命名为test.obj和main.obj),在main.cpp中,调用了f函数,然而当编译器编译main.cpp时,它所仅仅知道的只是main.cpp中所包含的test.h文件中的一个关于void f();的声明,所以,编译器将这里的f看作外部连接类型,即认为它的函数实现代码在另一个.obj文件中,本例也就是test.obj,也就是说,main.obj中实际没有关于f函数的哪怕一行二进制代码,而这些代码实际存在于test.cpp所编译成的test.obj中。在main.obj中对f的调用只会生成一行call指令,像这样: call f [C++中这个名字当然是经过mangling[处理]过的] 在编译时,这个call指令显然是错误的,因为main.obj中并无一行f的实现代码。那怎么办呢?这就是连接器的任务,连接器负责在其它的.obj中(本例为test.obj)寻找f的实现代码,找到以后将call f这个指令的调用地址换成实际的f的函数进入点地址。需要注意的是:连接器实际上将工程里的.obj“连接”成了一个.exe文件,而它最关键的任务就是上面说的,寻找一个外部连接符号在另一个.obj中的地址,然后替换原来的“虚假”地址。 这个过程如果说的更深入就是: call f这行指令其实并不是这样的,它实际上是所谓的stub,也就是一个jmp 0xABCDEF。这个地址可能是任意的,然而关键是这个地址上有一行指令来进行真正的call f动作。也就是说,这个.obj文件里面所有对f的调用都jmp向同一个地址,在后者那儿才真正”call”f。这样做的好处就是连接器修改地址时只要对后者的call XXX地址作改动就行了。但是,连接器是如何找到f的实际地址的呢(在本例中这处于test.obj中),因为.obj与.exe的格式是一样的,在这样的文件中有一个符号导入表和符号导出表(import table和export table)其中将所有符号和它们的地址关联起来。这样连接器只要在test.obj的符号导出表中寻找符号f(当然C++对f作了mangling)的地址就行了,然后作一些偏移量处理后(因为是将两个.obj文件合并,当然地址会有一定的偏移,这个连接器清楚)写入main.obj中的符号导入表中f所占有的那一项即可。 这就是大概的过程。其中关键就是: 编译main.cpp时,编译器不知道f的实现,所以当碰到对它的调用时只是给出一个指示,指示连接器应该为它寻找f的实现体。这也就是说main.obj中没有关于f的任何一行二进制代码。 编译test.cpp时,编译器找到了f的实现。于是乎f的实现(二进制代码)出现在test.obj里。 连接时,连接器在test.obj中找到f的实现代码(二进制)的地址(通过符号导出表)。然后将main.obj中悬而未决的call XXX地址改成f实际的地址。完成。 然而,对于模板,你知道,模板函数的代码其实并不能直接编译成二进制代码,其中要有一个“实例化”的过程。举个例子: //----------main.cpp------//template<class T>void f(T t){} int main(){…//do somethingf(10); // call f<int> 编译器在这里决定给f一个f<int>的实例…//do other thing} 也就是说,如果你在main.cpp文件中没有调用过f,f也就得不到实例化,从而main.obj中也就没有关于f的任意一行二进制代码!如果你这样调用了: f(10); // f<int>得以实例化出来f(10.0); // f<double>得以实例化出来 这样main.obj中也就有了f<int>,f<double>两个函数的二进制代码段。以此类推。 然而实例化要求编译器知道模板的定义,不是吗? 看下面的例子(将模板的声明和实现分离): //-------------test.h----------------//template<class T>class A{public:void f(); // 这里只是个声明}; //---------------test.cpp-------------//#include”test.h”template<class T>void A<T>::f() // 模板的实现{ …//do something} //---------------main.cpp---------------//#include”test.h”int main(){A<int> a;f(); // #1} 编译器在#1处并不知道A<int>::f的定义,因为它不在test.h里面,于是编译器只好寄希望于连接器,希望它能够在其他.obj里面找到A<int>::f的实例,在本例中就是test.obj,然而,后者中真有A<int>::f的二进制代码吗?NO!!!因为C++标准明确表示,当一个模板不被用到的时侯它就不该被实例化出来,test.cpp中用到了A<int>::f了吗?没有!!

‘陆’ C中预处理命令 #error 用法是怎么样的 请举例.

比如说你的源代码只能在Linux平台运行,那么可以有
#ifdef WIN32
#error This programme cannot compile @ Windows Platform
#endif
这样如果WIN32被定义过了,就不允许编译

‘柒’ 请问 c++中 模板是 编译时多态还是运行时多态,或者都不是,求解

是编译时多态。所有的模板都是在编译时产生对应的代码,它没有面向对象中的虚表,无法实现动态多态。

你仔细想一想,模板在应用时都必须指定确定的类型,而运行多态仅需指定一个基类就OK啦。

‘捌’ PSD模板 怎么替换里面的图片

工具:pscs6

1、打开ps的软件进入,然后把需要编辑的ps打开进入,如图所示,然后再右侧选中需要更换图片的图层。

‘玖’ template<class T>这种用法在C++中有吗什么意思怎么用

可以
template < typename T >
T max( T a, T b )
{
return a < b ? b : a;
}
这个 max 函数就是一个模板函数,它可以传入一个 “类型”的参数,以便实现任意类型求最大值的效果。假设我们这样使用它:
int x=5, y=10;
int z=max <int>( x, y );
这时候发生了什么呢?我们传入的“类型参数”是int,因此编译器在编译这段代码时会使用 int 来构造一个新函数:
int max( int a, int b )
{
return a < b ? b : a;
}
后面的事就和编译普通的函数一样了,C++编译器继续使用强类型系统编译这个函数,由强类型系统来检查这个函数是否正确。
这个过程叫做模板的“特化”,它发生在编译期,当编译器发现模板函数、模板类被使用(注意,不是定义)的时候进行的。这个系统实际上比较像宏,但是比宏更为智能。
很明显,编译器必须知道模板如何特化这个函数,因此模板函数的实现,必须在“使用点”之前,因此模板库只能通过头文件库的形式来提供。

‘拾’ office2007如何在编译过文件以后替换PPT模板

我也想知道如何实现这个功能。求大侠解答啊!

热点内容
传智播客php韩顺平 发布:2024-05-17 20:09:52 浏览:819
android蓝牙打印打印图片 发布:2024-05-17 18:58:31 浏览:464
android年龄 发布:2024-05-17 18:51:33 浏览:198
termux安装python 发布:2024-05-17 18:44:55 浏览:655
手机流量上传 发布:2024-05-17 18:44:06 浏览:551
服务器怎么证明是好的 发布:2024-05-17 18:39:28 浏览:683
树莓派如何搭建mqtt服务器 发布:2024-05-17 18:27:38 浏览:437
门口机sip服务器ip是什么 发布:2024-05-17 17:38:27 浏览:554
光遇安卓区是什么服 发布:2024-05-17 17:22:25 浏览:25
linux驱动开发教程 发布:2024-05-17 17:19:52 浏览:501