Reputation: 30655
How do I specialize initialize()
(see below) where the type isn't based on the method argument, just the overall class template parameter?
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;
};
Upvotes: 2
Views: 44
Reputation: 320777
Non-template members of class template are themselves independent templates. You can specialize them independently. In your case - by using explicit specialization
// 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("");
}
}
It is up to you to decide which version of the method is the "default" version and which is the "specialized" version. Or maybe you want to declare both versions as specializations.
For example, you might decide to consider both versions as specializations, while defining the main version as deleted
// 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()
{
}
Just keep in mind that an explicit specialization is no longer a template. It obeys ODR as an ordinary function. Even if your template class is defined in a header file (as template classes usually are), the definition of the above specialization(s) have to go to a .cpp
file. The header file should contain mere declarations for your specializations
// header file declarations
template<> void MyClass<std::ifstream>::initialize();
template<> void MyClass<std::stringstream>::initialize();
while the definitions should go to a .cpp
file.
Upvotes: 3
Reputation: 66230
What about using SFINAE to enable only the correct version?
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;
}
Upvotes: 0