基于整体 class 模板专门化 class 方法
Specializing a class method based on overall class template
我如何专门化 initialize()
(见下文),其中类型不是基于方法参数,而是整个 class 模板参数?
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;
};
class模板的非模板成员本身就是独立的模板。您可以独立地专门化它们。在你的情况下 - 通过使用显式专业化
// 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("");
}
}
哪个版本的方法是"default"版,哪个是"specialized"版,由你决定。或者您可能想将两个版本都声明为专业化。
例如,您可能决定将两个版本都视为专业化版本,同时将主要版本定义为已删除
// 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。即使您的模板 class 是在头文件中定义的(通常是模板 class),上述专业化的定义也必须转到 .cpp
文件中。头文件应仅包含 声明 用于您的专业
// header file declarations
template<> void MyClass<std::ifstream>::initialize();
template<> void MyClass<std::stringstream>::initialize();
而定义应该转到 .cpp
文件。
如果使用 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;
}
我如何专门化 initialize()
(见下文),其中类型不是基于方法参数,而是整个 class 模板参数?
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;
};
class模板的非模板成员本身就是独立的模板。您可以独立地专门化它们。在你的情况下 - 通过使用显式专业化
// 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("");
}
}
哪个版本的方法是"default"版,哪个是"specialized"版,由你决定。或者您可能想将两个版本都声明为专业化。
例如,您可能决定将两个版本都视为专业化版本,同时将主要版本定义为已删除
// 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。即使您的模板 class 是在头文件中定义的(通常是模板 class),上述专业化的定义也必须转到 .cpp
文件中。头文件应仅包含 声明 用于您的专业
// header file declarations
template<> void MyClass<std::ifstream>::initialize();
template<> void MyClass<std::stringstream>::initialize();
而定义应该转到 .cpp
文件。
如果使用 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;
}