Necesito implementar alguna comprobación de db usando macro.

Supongamos que tenemos algo como esto:

#define DB_CHECK(prop, records)      bool found = false; \
                                     for(auto i : records) \
                                       if(i.id == prop.id) found = true; break; \
                                       if(!found) PRINT_ERROR("Some error");

Y en el código lo llamo así:

std::list <RecordClass> recordsList;
std::list <AnotherClass> anotherClassList;
for(auto &i : myDBrecords)
{
   DB_CHECK(i, recordsList);
   DB_CHECK(i, anotherClassList);
}

Para esto obtengo un error para la inicialización booleana found.

'encontrado': redefinición; inicialización múltiple

¿Tienes alguna idea de cómo puedo evitar esto? ¿Proporciona otro argumento para found en macro?

c++
0
harunB10 25 jun. 2020 a las 19:08

2 respuestas

Otro enfoque es usar la macro __COUNTER__ para crear un nombre de variable único.

#define TIE_VARIABLE_NAME_IMPL(name, count) name##count
#define TIE_VARIABLE_NAME(name, count) TIE_VARIABLE_NAME_IMPL(name, count)
#define UNIQUE_NAME(name) TIE_VARIABLE_NAME(name, __COUNTER__)

#define DB_CHECK_IMPL(prop, records, unique_found, unique_i)  \
{bool unique_found = false; \
for(auto unique_i : records) \
    if(unique_i.id == prop.id){ unique_found = true; break;} \
if(!unique_found) PRINT_ERROR("Some error");}

#define DB_CHECK(prop, records) DB_CHECK_IMPL(prop, records, UNIQUE_NAME(found), UNIQUE_NAME(i))

Aprendí sobre este enfoque de esta biblioteca aquí https: / /github.com/ned14/outcome/blob/develop/include/outcome/try.hpp#L145

En su caso, veo el enfoque mencionado en la otra respuesta como una solución más simple para su problema, pero esta es una alternativa manera de resolver el problema y puede ser útil en otras implementaciones de macros donde, por cualquier razón, crear un alcance adicional no es deseable.

Este enfoque también evita las advertencias de sombreado (por ejemplo, -Wshadow) en este tipo de escenario:

bool found = false; // user has a variable named `found` in the scope
DB_CHECK(i, recordsList); // we dont shadow the users `found` because we used a unique name

Para obtener más información sobre la macro de contador: https: //gcc.gnu. org / onlinedocs / cpp / Common-Predefined-Macros.html también no estoy seguro de cuán ampliamente es compatible con esa macro, pero msvc, clang y gcc parecen ser compatibles.

0
UnforeseenPrincess 25 jun. 2020 a las 17:22

Es un error de compilación, causado por una segunda llamada a la macro DB_CHECK. Declara "bool found" nuevamente en el mismo alcance de visibilidad. Puede resolver el problema entre corchetes {}, esto separará los ámbitos de visibilidad:

#define DB_CHECK(prop, records)      {bool found = false; \
                                     for(auto i : records) \
                                       if(i.id == prop.id) found = true; break; \
                                       if(!found) PRINT_ERROR("Some error");}

O al encerrar las llamadas

for(auto &i : myDBrecords)
{
   {DB_CHECK(i, recordsList);}
   {DB_CHECK(i, anotherClassList);}
}
3
armagedescu 25 jun. 2020 a las 16:14