Reputation: 17
how to template the below code? First, I have a Book as base:
class Book {
public:
Book() {}
~Book() {}
}
Then ComputerBook:
class ComputerBook: public Book {
public:
static ComputerBook* create() {
return new ComputerBook();
}
private:
ComputerBook ():Book() {}
}
Then PhoneBook:
class PhoneBook: public Book {
public:
static PhoneBook* create() {
return new PhoneBook();
}
private:
PhoneBook():Book() {}
}
PhoneBook has two inheritances:
class PhoneBook1: public PhoneBook {
public:
static PhoneBook1* create() {
return new PhoneBook1();
}
private:
PhoneBook1():PhoneBook() {}
}
class PhoneBook2: public PhoneBook {
public:
static PhoneBook2* create() {
return new PhoneBook2();
}
private:
PhoneBook2():PhoneBook() {}
}
So that can merge ComputerBook and PhoneBook1, PhoneBook2 into one with template?
Upvotes: 1
Views: 2106
Reputation: 10939
What you want is (probably) CRTP. You define your method create
in the base class where it is parametrized with the derived class which is a template parameter. When inheriting from the template base you plug in the derived class and magically get the create
function with the correct type.
I don't get why you have a private constructor or why you need this factory function at all though.
template < typename Derived >
class Book {
friend Derived;
public:
Book() {}
~Book() {}
static Derived* create() {
return new Derived{};
}
};
class ComputerBook: public Book<ComputerBook> {
// Make the base class a friend so we can access the private constructor
friend class Book<ComputerBook>;
private:
ComputerBook() : Book() {}
};
template < typename Derived >
class PhoneBook: public Book<Derived> {}; // no private constructor, no 'friend' needed
class PhoneBook1: public PhoneBook<PhoneBook1> {};
class PhoneBook2: public PhoneBook<PhoneBook2> {};
int main()
{
auto cb = ComputerBook::create();
auto pb1 = PhoneBook1::create();
auto pb2 = PhoneBook2::create();
delete cb;
delete pb1;
delete pb2;
}
Upvotes: 1
Reputation: 196
From what it looks like you are trying do do, you are making a static factory method called create
for all of your books. You can templatize this method like this:
class Book {
public:
Book() {}
~Book() {}
template<typename T>
static Book* create() {
return new T();
}
}
And then to make a phone book:
Book::create<PhoneBook1>();
Also make sure the constructors for each of the books are public, or friends of the Book::create
static method.
Upvotes: 2