Специализация метода класса на основе общего шаблона класса - PullRequest
0 голосов
/ 26 января 2019

Как мне специализировать initialize() (см. Ниже), где тип не основан на аргументе метода, только на общем параметре шаблона класса?

template<class STREAM_TYPE>
class MyClass
{
    struct MyStruct
    {
        STREAM_TYPE* _ifs{nullptr};
    }

public:   

    // Use this when STREAM_TYPE = std::ifstream
    void initialize()
    {
        for(MyStruct& ms : _myStructs)
        {
            ms._ifs = new std::ifstream("");
        }
    }

    // Use this when STREAM_TYPE = std::stringstream
    void initialize()
    {
    }

private:
    std::array<MyStruct, 10> _myStructs;
};

Ответы [ 2 ]

0 голосов
/ 26 января 2019

А как насчет использования SFINAE для включения только правильной версии?

  template <typename ST = STREAM_TYPE>
  std::enable_if_t<std::is_same<ST, std::ifstream>::value> initialize ()
   {
     std::cout << "ifstream case" << std::endl;

     for (MyStruct & ms : _myStructs)
        ms._ifs = new std::ifstream("");
   }

  template <typename ST = STREAM_TYPE>
  std::enable_if_t<std::is_same<ST, std::stringstream>::value> initialize ()
   {
     std::cout << "stringstream case" << std::endl;
   }
0 голосов
/ 26 января 2019

Не шаблонные члены шаблона класса сами являются независимыми шаблонами. Вы можете специализировать их самостоятельно. В вашем случае - с помощью явной специализации

// Main template
template<class STREAM_TYPE>
class MyClass
{
    void initialize()
    {
    }
};

// Specialization, declared outside the main template definition
template<>
void MyClass<std::ifstream>::initialize()
{
    for(MyStruct& ms : _myStructs)
    {
        ms._ifs = new std::ifstream("");
    }
}

Вам решать, какая версия метода является версией по умолчанию, а какая - специализированной. Или, может быть, вы хотите объявить обе версии как специализации.

Например, вы можете решить рассматривать обе версии как специализации, при этом определяя основную версию как удаленную

// Main template
template<class STREAM_TYPE>
class MyClass
{
    void initialize() = delete;
};

// Specialization, declared outside the main template definition
template<>
void MyClass<std::ifstream>::initialize()
{
    for(MyStruct& ms : _myStructs)
    {
        ms._ifs = new std::ifstream("");
    }
}

template<>
void MyClass<std::stringstream>::initialize()
{
}

Только помните, что явная специализация больше не является шаблоном. Он подчиняется ODR как обычная функция. Даже если ваш шаблонный класс определен в заголовочном файле (как это обычно бывает с шаблонными классами), определение вышеуказанных специализаций должно идти в файл .cpp. Заголовочный файл должен содержать простые объявления для вашей специализации

// header file declarations
template<> void MyClass<std::ifstream>::initialize();
template<> void MyClass<std::stringstream>::initialize();

в то время как определения должны идти в файл .cpp.

...