5

我必须根据编译时间常数参数编写相同的代码,例如:

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宏系列),但我找不到针对我的具体问题的解决方案。

你有解决这个问题的方法吗?

4

3 回答 3

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];
}

如果性能被证明是一个问题,那么您可以尝试基于宏的更核心的方法。但是,如果您的测量结果不会显示显着的开销,则更喜欢简单明了,并展开一个简单的循环。

于 2013-03-29T09:17:11.517 回答
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 "),你可以这样做。

于 2013-03-29T09:06:50.550 回答
0

重复对我来说似乎不是问题,但是 int 到 string 的编译时转换和随后的连接确实如此。可以通过以下技术(未经测试)解决重复问题:

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

于 2013-03-29T09:33:08.300 回答