有条件的宏文本替换 [英] Conditional macro text replacement

查看:146
本文介绍了有条件的宏文本替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的直觉是这不可能,但我不是专家. 这是我想做的:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆