Возможно ли в C++ в качестве параметра шаблона как-то задать поле класса/структуры?

Рейтинг: 1Ответов: 1Опубликовано: 24.01.2023

Как известно, параметрами шаблона в C++ могут быть типы данных, константы, указатели... А существует ли способ каким-либо образом параметризовать идентификаторы полей классов или структур? Вот пример, иллюстрирующий мой вопрос:

#include <stdio.h>


struct TEST_STRUC
{
    int a;
    int b;

    TEST_STRUC(int val_a, int val_b): a(val_a), b(val_b) {}
};


template </*как-то определяем параметр-поле*/ F, class TClass>
void PrintCompare(TClass* pCls1, TClass* pCls2)
{
    if (pCls1->F > pCls2->F) puts("Greater than");
    else if (pCls1->F < pCls2->F) puts("Lower than");
    else puts("Equal");
}


//.............

int main()
{
    TEST_STRUC t1(7,4), t2(8,2);

    PrintCompare<a>(&t1, &t2);
    PrintCompare<b>(&t1, &t2);

    return 0;
}

Сразу оговорюсь: вариант замены полей на массив (и использование константных параметров-индексов, вместо полей) не интересен.

Ответы

▲ 0

Большое спасибо за комменты! Вариант, наиболее близкий к тому, что мне нужен, - это предложенный @HolyBlackCat, с указателями на члены. В общем, пока что я пришёл к подходу, который иллюстрирует код ниже. Насколько он удачен, покажет решение моей конкретной задачи. Совсем без макросов обойтись не получилось, т.к. "чистый" синтаксис вышел уж больно многословный. Буду рад комментариям с замечаниями и предложениями по улучшению подобного кода...

#include <stdio.h>


template <class TClass, int TClass::*F>
class Mgr
{
public:
    static void PrintCompare(TClass* pCls1, TClass* pCls2)
    {
        if (pCls1->*F > pCls2->*F) puts("Greater than");
        else if (pCls1->*F < pCls2->*F) puts("Lower than");
        else puts("Equal");
    }
};

#define FRIEND_MGR              template <class TClass, int TClass::*F> friend class Mgr 
#define USE_MGR(class,field)    typedef Mgr<class, &class::field>


class CTestClass
{
    FRIEND_MGR;

    int a;
    int b;

public:
    USE_MGR(CTestClass, a) MgrA;
    USE_MGR(CTestClass, b) MgrB;

    CTestClass(int val_a, int val_b): a(val_a), b(val_b) {}
};


int main()
{
    CTestClass t1(7,4), t2(8,2);

    CTestClass::MgrA::PrintCompare(&t1, &t2);
    CTestClass::MgrB::PrintCompare(&t1, &t2);

    return 0;
}