Reputation: 7994
I have the following class:
template <typename T>
class Fixed2DContainer {
T* ptr;
public:
const int total_cols;
const int total_rows;
Fixed2DContainer(int cols, int rows);
T& operator()(int col_n, int row_n);
~Fixed2DContainer();
private : //disallow copy
Fixed2DContainer& operator=(const Fixed2DContainer&);
Fixed2DContainer operator()(const Fixed2DContainer&);
};
Now I'd like to specialize this template for some class so that the only change is that I can have an another constructor. Basically I want to be able to do:
Fixed2DContainer<Image>("filename.jpg");
is there an elegant way to do this? I am fairly new to template so i have no idea of the difficulty
Upvotes: 0
Views: 788
Reputation: 208343
If your compiler supports it, C++11 has inheriting constructors that will pretty much get you where you want to be:
template <typename T>
class Base {}; // has all the implementation
template <typename T>
class Template {
using Base::Base;
//Template() = delete; // You might need this if you don't want
// the default constructor
};
template <>
class Template<int> {
using Base::Base;
Template( std::string const & x ) {}
//Template() = delete; // You might need this if you don't want
// the default constructor
};
Upvotes: 3
Reputation: 2942
I have had the same problem myself. Unfortunately, every constructor must exist in the generic template. You can avoid people using the wrong constructor at runtime though;
template <typename T>
class Fixed2DContainer {
// omitted
Fixed2DContainer(string fileName)
{
// Do not allow construction of Fixed2DContainer with
// string argument in general case
ASSERT(false);
// or
throw new ExceptionType("Not implemented");
}
// omitted
};
template<>
class Fixed2DContainer<Image> {
// omitted
Fixed2DContainer(string fileName)
{
// Actual construction code
}
// omitted
};
Asserts are preferred because your code will break on the assert whereas the in the exception case it will break on the catch, making it slightly harder to debug.
Upvotes: 0
Reputation: 171263
Here's a quick example of what I meant in my earlier comment ...
template <typename T>
class Fixed2DContainerBase {
T* ptr;
public:
const int total_cols;
const int total_rows;
Fixed2DContainerBase(int cols, int rows);
T& operator()(int col_n, int row_n);
~Fixed2DContainerBase();
private : //disallow copy
Fixed2DContainerBase& operator=(const Fixed2DContainerBase&);
Fixed2DContainerBase(const Fixed2DContainerBase&);
};
// primary template
template <typename T>
class Fixed2DContainer : public Fixed2DContainerBase<T> {
Fixed2DContainer(int cols, int rows);
~Fixed2DContainer();
};
// explicit specialization
template <>
class Fixed2DContainer<Image> : public Fixed2DContainerBase<Image> {
Fixed2DContainer(int cols, int rows);
Fixed2DContainer(const std::string&);
~Fixed2DContainer();
};
N.B. because the base class is non-copyable the derived classes will be too. It may not be necessary to define a destructor in the derived classes if all the cleanup can be done by the base destructor.
Upvotes: 1