有条件的宏文本替换 [英] Conditional macro text replacement
问题描述
我的直觉是这不可能,但我不是专家. 这是我想做的:
My gut feeling is that this isn't possible but I'm no expert. Here's what I would like to do:
#define KEY(i) #if (i == 0) KeyClassA(arg.fieldA)
#elif (i == 1) KeyClassB(arg.fieldB)
//...
#endif
//inside a function with given arg
for(int i = 0; i < N; i++) {
Data* data = array[i]->find(KEY(i));
//do things with data
}
该代码显然比C ++代码更多的是伪代码,我个人不认为这样的东西可以编译,但是我的意图应该很明确:根据适当的数据结构,为find函数提供一个临时类对象.数组.也就是说,数组中的每个数据结构都需要一个不同的键匹配类.
That code is obviously more pseudo-code than C++ code and I personally don't think anything like this will compile, but my intention should be clear: provide a temporary class object to the find function according to the appropriate data structure in the array. That is, each data structure in the array requires a different key matching class.
宏文本替换似乎是尝试实现此目的的最聪明"方法,但我显然会欢迎其他任何想法来使此类工作正常进行.
Macro text replacement seems like the "cleverest" way to attempt to achieve this but I would obviously welcome any other ideas to get something like this to work.
推荐答案
宏文本替换不是您的问题的解决方案,因为索引i
仅在运行时才知道.宏甚至在编译开始之前就已处理.
Macro text replacement is a non-solution to your problem because the index i
is known only at runtime. Macros are processed before compilation even begins.
如果N
在编译时未知,那么您将需要使用条件结构和可能的循环的某种组合.如果KeyClass*
的数量是固定的(似乎是这种情况),则您可以执行以下操作:
If N
is not known at compile-time, then you will need to use some combination of conditional structures and possibly a loop. If the number of KeyClass*
es are fixed (which appears to be the case), you may be able to do something like this:
void Foo(int N, Array& array, const Bar& arg)
{
if(N > 3 || N <= 0) return;
Data* data = array[0]->find(KeyClassA(arg.fieldA));
// DoSomething(data);
if(N == 1) return;
data = array[1]->find(KeyClassB(arg.fieldB));
// DoSomething(data);
if(N == 2) return;
data = array[2]->find(KeyClassC(arg.fieldC));
// DoSomething(data);
}
将所有通用代码放入DoSomething()
函数中(最好使用更好的函数名),这样您就不必重复输入N
的所有可能有效值了.
Put all the common code in the DoSomething()
function (preferably using a better function name) so you don't repeat yourself for all possible valid values for N
.
如果N
在编译时是已知的,则只需展开循环即可.
If N
is known at compile-time however, you can simply unroll the loop.
void Foo(Array& array, const Bar& arg)
{
Data* data = array[0]->find(KeyClassA(arg.fieldA));
// DoSomething(data);
data = array[1]->find(KeyClassB(arg.fieldB));
// DoSomething(data);
data = array[2]->find(KeyClassC(arg.fieldC));
// DoSomething(data);
}
如果您不想自己展开循环,甚至可以看上模板元编程,尽管这可能对您正在做的事情来说是过大的:
You can even get fancy with template metaprogramming if you much rather not unroll the loop yourself, although this might be overkill for what you're doing:
// The basic idea using template specializations
template<int i>
struct GetKey;
template<>
struct GetKey<0>
{
KeyClassA From(const Bar& arg) { return KeyClassA(arg.fieldA); }
};
template<>
struct GetKey<1>
{
KeyClassB From(const Bar& arg) { return KeyClassB(arg.fieldB); }
};
template<>
struct GetKey<2>
{
KeyClassC From(const Bar& arg) { return KeyClassC(arg.fieldC); }
};
template<int i, int N>
struct Iterate
{
static void Body(Array& array, const Bar& arg)
{
Data* data = array[i]->find(GetKey<i>().From(arg));
// DoSomething(data);
Iterate<i+1, N>::Body(array, arg);
}
};
template<int N>
struct Iterate<N, N>
{
static void Body(Array& array, const Bar&) {}
};
void Foo(Array& array, const Bar& arg)
{
Iterate<0, 3>::Body(array, arg);
}
这篇关于有条件的宏文本替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!