【发布时间】:2012-02-19 05:06:31
【问题描述】:
如果我有一个包含一堆其他代码的模板。 g++ 会为模板的每个版本重新生成所有相同的代码吗?
例如:
template <typename> T
T parseSomething(const std::string& data) {
// Some state variables go here
enum State {state1,state2,state3} state;
for(std::string::const_iterator i=data.begin();i!=data.end();++i) {
// Some big testy stuff to see if we got in the right place
switch (state) {
case state1: {
switch (*i) {
case f: // ...
// ... lots of switchy stuff here ..
return T(*i);
}
}
所以在那个 func 中.. 唯一真正需要模板的是 return T(*i) 行。
假设我用 4 个不同的 T 实例化它,例如。
parseSomething<float>(data);
parseSomething<int>(data);
等等
g++ 是否会为每个 T 单独生成所有其他代码(循环和开关部分)?
或者只生成一次开关和循环是否足够聪明.. 然后为每个 T.. 生成返回 T(*i);行吗?
我尝试过测试,使用 -O0 肯定会在任何地方复制开关,但使用 -O2 及以上则很难判断;它看起来更聪明..但它太聪明了,我无法破译 ASM :)
这是我试图用来测试的示例程序。
编译:
g++ -std=c++0x -fverbose-asm -ggdb3 -fvar-tracking-assignments -O6 -march=native codegen.cpp
运行:
gdb --args ./a.out asdf1111
偏执代码版本:
#include <iostream>
#include <string>
using namespace std;
char getSomething(const string& myString) {
for(auto myPlase=myString.begin();myPlase!=myString.end();++myPlase) {
if (*myPlase == 'f') {
return *(myPlase+1);
}
}
}
template <typename T>
T getSomething(const string& myString) {
return T(getSomething(myString));
}
int main(int argc, char** argv) {
string base = argv[1];
float myFloat = getSomething<float>(base);
int myInt = getSomething<int>(base);
char myChar = getSomething<char>(base);
//string newString = getSomething<string>(base);
cout << myFloat << " " << myInt << " " << myChar << endl;
}
我想使用的代码版本:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
T getSomething(const string& myString) {
for(auto myPlace=myString.begin();myPlace!=myString.end();++myPlace) {
if (*myPlace == 'f') {
return T(*(myPlace+1));
}
}
}
int main(int argc, char** argv) {
string base = argv[1];
float myFloat = getSomething<float>(base);
int myInt = getSomething<int>(base);
char myChar = getSomething<char>(base);
//string newString = getSomething<string>(base);
cout << myFloat << " " << myInt << " " << myChar << endl;
}
【问题讨论】:
-
在现实世界的程序中,我使用 ragel 生成代码,大约有 1200 行。我想把它变成一个模板函数,主要的模板位是返回类型,但我不希望看到为每种类型重新生成这 1200 行。
-
如果你是 GCC,你会如何生成有问题的代码?
-
当然真正的问题是:在偏执的代码示例中,对
getsomething的调用是否内联:)? -
为什么不直接从解析中提取转换?这将保证一个函数,你甚至可以现在转发声明它并且只在一个翻译单元中实现它。为什么不能只返回
*i返回的任何内容并在调用站点进行转换? -
是的,我想这就是我要走的路。解析可以从 *i 中生成类型,或者通过解析一系列字符来构建结果。我要看看我是否可以将解析分成不同的函数并采用“偏执狂”的方式。
标签: c++ templates c++11 metaprogramming