Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

Компиляция методов в шаблонном классе в зависимости от параметра шаблона

#cpp #шаблоны_с++


Хочу написать шаблонный класс, который будет получать в качестве параметра шаблона
другой шаблонный класс.

Проблема в том, что среди шаблонов, которые будут параметрами, есть различные классы,
которые имеют несколько отличающийся интерфейс и поэтому при компиляции возможны ошибки
из-за несоответствия интерфейсов.

Как, например, ниже:

#include 

template  class FirstCreator
{
public:
    typedef T object_type;

    T* GetNewObject()
    {
        T* pT = new T();
        return pT;
    }
};

template  class SecondCreator
{
public:
    typedef T object_type;

    std::shared_ptr GetNewObjectEx()
    {
        std::shared_ptr pT;
        return pT;
    }
};

template  class CreatorUser
{
public:
    TCreator* m_pData;

    CreatorUser(TCreator& data)
    {
        m_pData = &data;
    }

    typename TCreator::object_type* GetNewObjectPtr()
    {
        return m_pData->GetNewObject();
    }

    std::shared_ptr GetNewObjectSharedPtr()
    {
        return m_pData->GetNewObjectEx();
    }

    void SimpleFunction()
    {
        //Здесь на самом деле нужен вызов только одной фукнции:
        //GetNewObjectPtr, если параметр шаблона FirstCreator
        //GetNewObjectSharedPtr, если параметр шаблона SecondCreator
        //но как дать понять компилятору это?
        typename TCreator::object_type* pObj = GetNewObjectPtr();
        delete pObj;

        std::shared_ptr pObjShared = GetNewObjectSharedPtr();
    }
};

typedef FirstCreator IntCreatorFirst;
typedef SecondCreator IntCreatorSecond;

int main()
{
    IntCreatorFirst creator1;
    IntCreatorSecond creator2;

    CreatorUser* pCreatorUser1 = new CreatorUser(creator1);
    CreatorUser* pCreatorUser2 = new CreatorUser(creator2);

    pCreatorUser1->SimpleFunction();
    pCreatorUser2->SimpleFunction();

    return 0;
} 


При попытке вызвать SimpleFunction компилятор выдает ошибку 


  Error 1   error C2039: 'GetNewObjectEx' : is not a member of
  'FirstCreator'


Что совершенно справедливо, так как такой функции у FirstCreator действительно нет.

Мне нужно написать SimpleFunction таким образом, чтобы если параметром CreatorUser
является FirstCreator, то вызывался метод GetNewObjectPtr, а метод GetNewObjectSharedPtr
вообще не создавался и наоборот.

Есть ли в C++ возможность сделать подобное?

UPD:

Исправил в соответствии с первым ответом, заработало. Пришлось правда завернуть функции
в другую функцию - но тут, наверное, проблема старого компилятора (компилятор студии
MS VS 2010), который все время ругался, что функция не может иметь шаблонных параметров
по умолчанию:

void SimpleFunctionEx()
{
    SimpleFunction();
}

template
void SimpleFunction(typename std::enable_if >::value>::type* = nullptr)
{
    typename TCreator::object_type* pObj = GetNewObjectPtr();
    delete pObj;
}

template
void SimpleFunction(typename std::enable_if >::value>::type* = nullptr)
{
    std::shared_ptr pObjShared = GetNewObjectSharedPtr();
}

    


Ответы

Ответ 1



Можно попробовать использовать SFINAE: template void SimpleFunction(typename std::enable_if::value>::type* = nullptr) { // Используем GetNewObjectPtr. } template void SimpleFunction(typename std::enable_if::value>::type* = nullptr) { // Используем GetNewObjectSharedPtr. }

Ответ 2



Самый простой способ, это воспользоваться специализацией шаблона: template class CreatorUser; template<> class CreatorUser { public: FirstCreator* m_pData; CreatorUser(FirstCreator& data) { m_pData = &data; } FirstCreator::object_type* GetNewObjectPtr() { return m_pData->GetNewObject(); } void SimpleFunction() { FirstCreator::object_type* pObj = GetNewObjectPtr(); delete pObj; } }; template<> class CreatorUser { public: SecondCreator* m_pData; CreatorUser(SecondCreator& data) { m_pData = &data; } std::shared_ptr GetNewObjectSharedPtr() { return m_pData->GetNewObjectEx(); } void SimpleFunction() { std::shared_ptr pObjShared = GetNewObjectSharedPtr(); } }; Код я не проверял, поэтому могут быть опечатки, но суть должна быть ясна.

Комментариев нет:

Отправить комментарий