Есть ли шаблон (или нечто похожее) для имён полей структуры?

Допустим у меня есть код на поиск элемента в массиве структур. Поиск может осуществляться по разным полям структуры. Соответственно нужно отдельно прописывать эти поля каждый раз и получается не очень красиво. Может есть какой-то способ обобщить?

if (key == 1)
        {
            for (int i = 0; i < size; i++)
                if (!strcmp(query,p[i].name))
                    return i;
            return -1;
        }
        else if (key == 2)
        {
            for (int i = 0; i < size; i++)
                if (!strcmp(query, p[i].surname))
                    return i;
            return -1;
        }
        else if (key == 3)
        {
            for (int i = 0; i < size; i++)
                if (!strcmp(query,p[i].zodiak))
                    return i;
            return -1;
        }

Ответы (5 шт):

Автор решения: Harry

Извините, что ответом, это скорее комментарий, но иначе не влезет.

А почему не сделать

for (int i = 0; i < size; i++)
    if (!strcmp(query,
                key == 1 ? p[i].name :
                key == 2 ? p[i].surname :
                key == 3 ? p[i].zodiak : nullptr ))
        return i;
return -1;

Ну, nullptr, понятно, надо заменить или проверять key заранее, но идея, думаю, понятна?

→ Ссылка
Автор решения: Artyomka

Решение с оператором switch уже выглядит попроще, но далеко до идеала.

for (int i = 0; i < size; ++i)
{
    switch (key)
    {
    case 1:
        if (!strcmp(query, p[i].name)) return i;
        break;

    case 2:
        if (!strcmp(query, p[i].surname)) return i;
        break;

    case 3:
        if (!strcmp(query, p[i].zodiak)) return i;
        break;

    default:
        return -1;
    }
}
return -1;
→ Ссылка
Автор решения: Chorkov

Здесь просятся указатели на члены класса.

struct Foo // предполагаемая струкутура данных 
{
    char * name;
    char * surname;
    char * zodiak;
    // ... 
};
typedef char* (Foo::* fooMemderPtr);
// таблица номеров полей структуры
static const std::map< int, fooMemderPtr > fooMembersList={ 
    { 1, & Foo::name }, 
    { 2, & Foo::surname }, 
    { 3, & Foo::zodiak}, 
};

... 

fooMemderPtr memberPtr = fooMembersList.at(key);
for (int i = 0; i < size; i++)
    if (!strcmp(query,  p[i].*memberPtr))
        return i;
return -1;
→ Ссылка
Автор решения: LShadow77

Ну я бы, например, так это реализовал:

#define NUM_KEYS 3

struct Foo // предполагаемая струкутура данных 
{
    union
    {
        char* keys[NUM_KEYS];
        struct
        {
            char* name;
            char* surname;
            char* zodiak;
        };
    };
    // ... 
};

/*
 * ......................
 */

assert ((key>=1) && (key<=NUM_KEYS));

--key;
for (int i = 0; i < size; i++)
    if (!strcmp(query,p[i].keys[key])) return i;
return -1;
→ Ссылка
Автор решения: AR Hovsepyan

Если на С++, то все проще. Например:

class Names {   
    const std::array<std::string_view, 3> p;
public:
    constexpr Names(const std::array<std::string_view, 3>& names)
        noexcept : p(names){} 
    [[nodiscard]]   bool 
    find_name(std::string_view query,
        const size_t key) const noexcept 
    {
        if (!key || key > 3)
            return false;
        return query == p[key - 1];
    }
    //...
};


int main()
{
    constexpr Names n({ "one", "two", "three" });
    cout << n.find_name("two", 1);
    return 0;
}
→ Ссылка