Замена макрокоманды не является решением вашей проблемы, поскольку индекс i
известен только во время выполнения. Макросы обрабатываются еще до начала компиляции.
Если N
неизвестно во время компиляции, вам нужно будет использовать некоторую комбинацию условных структур и, возможно, цикла. Если число KeyClass*
является фиксированным (что, как представляется, имеет место), вы можете сделать что-то вроде этого:
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
.
Если во время компиляции известен N
, вы можете просто развернуть цикл.
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);
}
Вы можете даже полюбить шаблонное метапрограммирование, если не хотите сами развернуть цикл, хотя это может быть излишним для того, что вы делаете:
// 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);
}