我必须编写依赖于编译时常量参数的相同代码,例如:
map["text 0"] = vec[0];
map["text 1"] = vec[1];
...
map["text n"] = vec[n];
问题是我在编写代码时不知道n
,我将其作为模板参数接收。显而易见的解决方案是使用一个循环并在循环内生成"text k"
并使用vec[k]
,但这应该在编译时完成运行时开销。另一个解决方案是将函数专门用于不同的N
值,但是这样我将不得不多次手动编写相同的代码,并且没有理由将其作为模板。
我知道有一些智能宏可以重复类似的事情N次(比如BOOST_PP_REPEAT
宏系列),但我找不到一个针对我特定问题的解决方案。
你有解决这个问题的方法吗?
答案 0 :(得分:4)
除非您确实真的严格的性能限制,否则没有理由担心运行时开销。无论如何,插入都将在运行时执行,插入时间肯定会占据更改字符串中字符所需的时间。
此外,宏很难调试和维护:尽可能避免使用它们。在这里,我建议展开一个简单的循环:
std::string s = "text 0";
std::map<std::string, int> m;
for (int i = 0; i < N; i++)
{
m[s] = vec[i];
s[5] = '1' + i; // This is going to be the run-time overhead...
}
如果您的数字增长高于9
,则在C ++ 11中您可以使用to_string()
函数将整数转换为字符串:
std::string const s = "text ";
std::map<std::string, int> m;
for (int i = 0; i < N; i++)
{
m[s + std::to_string(i)] = vec[i];
}
如果性能将被证明是一个问题,那么您可以尝试基于宏的更硬核方法。但是,如果您的测量值不会显示出显着的开销,更喜欢简单明了并展开一个简单的循环。
答案 1 :(得分:0)
我相信以下内容应该有效:
#include <boost/preprocessor.hpp>
//... or just the required sub-headers
// Will generate code for 0, 1, ... (N_END - 1)
#define N_END 10
#define ONE_ASSIGNMENT(maZ, maIter, maData) \
if (maIter <= n) map["text " BOOST_PP_STRINGIZE(maIter)] = vec[maIter];
BOOST_PP_REPEAT(N_END, ONE_ASSIGNMENT, %%) //this generates the code
#undef ONE_ASSIGNMENT
#undef N_END
请注意,if()
会将字面值与模板参数(n
)进行比较,因此任何值得使用它的优化器都会从中生成无分支代码。
我使用%%
作为“此值永远不会被使用”。它被传递到maData
参数,所以如果你有一些有用的东西可以实际传递(例如"text "
),你可以改为。
答案 2 :(得分:0)
重复对我来说似乎不是问题,但是int的编译时转换为字符串以及后续的连接。重复问题可以通过以下技术解决(未经测试):
template<k,l> struct fill_vector {
static void doIt (... & vec) {
vec [INT_TO_TEXT (k)] = k;
fill_vector<k+1,l-1>::doIt (vec);
}
};
template<k> struct fill_vector<k,0> {
static void doIt (... & vec) {
vec [INT_TO_TEXT (k)] = k;
}
};
//...
fill_vector<0,n>::doIt (vec);
也许有人知道如何实施INT_TO_TEXT