基于整体类模板专门化类方法

时间:2019-01-26 16:50:48

标签: c++ templates template-specialization

在类型不是基于方法参数而是仅基于整个类模板参数的情况下,如何专门研究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 :(得分:3)

类模板的非模板成员本身就是独立的模板。您可以独立地专门化它们。在您的情况下-通过使用显式专业化

// 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文件中。

答案 1 :(得分:0)

使用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;
   }