Я использовал следующий подход для регистрации функций, но вы можете попробовать применить его в вашем случае, надеюсь, это оправдывает обходной путь в стиле C, который не учитывает пробелы:
#define GET_COMBO_BOX(x,y) x ## y
for (int i = 1; i < numberOfBoxes; i++)
GET_COMBO_BOX(comboBox1,i);
Это, очевидно, НЕ будет делать то, что вы хотите, так как i определяется во время компиляции, а макрос расходуется на предварительную обработку, но это даст вам представление о том, как предварительно генерировать вызовы функций.
Вот более полный пример, где используется конкатенация макросов:
#include<iostream>
#include<string>
using namespace std;
template< class E > struct EnumNames
{
static const char* const* names;
static int names_size;
};
#define REGISTER_ENUM( e ) \
const char* const* EnumNames< e >::names = e ## _names; \
int EnumNames< e >::names_size = sizeof( e ## _names ) / sizeof( const char* );
enum ElementType { NEURON, SYNAPSE };
const char* const ElementType_names[] = { "N", "S" };
REGISTER_ENUM( ElementType )
enum TokenMainType { EP, IP, NT, AI };
const char* const TokenMainType_names[] = { "EP", "IP", "NT", "AI" };
REGISTER_ENUM( TokenMainType )
template<class E>
ostream& operator <<(ostream& os, const E& e)
{
if (e > EnumNames< E >::names_size)
cout << "Error" << endl;
os << EnumNames< E >::names[e];
return os;
}
template<class E>
istream& operator >>(istream& is, E& e) {
std::string tmp_e_string;
is >> tmp_e_string;
for (int i = 0; i < EnumNames< E >::names_size; ++i) {
if (tmp_e_string == EnumNames< E >::names[i])
{
e = E(i);
return is;
}
}
cerr << "Fehler: tmp_nntype_string: " << tmp_e_string << endl;
return is;
}
int main (int argc, char **argv)
{
ElementType test1(NEURON);
cout<<string(EnumNames<ElementType>::names[test1])<<endl;
}