Factory specialization

D

Dave

Hello all,

Please see my question embedded in comment form below.

Thanks,
Dave

#include <iostream>
#include <boost/shared_ptr.hpp>

using namespace std;
using namespace boost;

// A base class
class Deleter
{
public:
Deleter() {}
virtual ~Deleter() {}
};

// A derived class
class MyClass: public Deleter
{
public:
MyClass(int data): m_data(data) {}
virtual ~MyClass() {}

void DoIt() const
{
cout << m_data << endl;
}

private:
int m_data;
};

// A factory for objects that are constructed with 0 or 1 parameters.
template <class T>
class Factory
{
public:
static shared_ptr<T> Create()
{
cout << "Primary Factory invoked" << endl;
return shared_ptr<T>(new T());
}

template <class P1>
static shared_ptr<T> Create(P1 p1)
{
cout << "Primary Factory invoked" << endl;
return shared_ptr<T>(new T(p1));
}
};

// Here's where I don't have things right. I'd like to specialize Factory
for types derived from Deleter.
// How may I do so?
template <class T> // ?????????????
class Factory<Deleter> // ?????????????
{
static shared_ptr<T> Create()
{
cout << "Specialized Factory invoked" << endl;
return shared_ptr<T>(new T());
}

template <class P1>
static shared_ptr<T> Create(P1 p1)
{
cout << "Specialized Factory invoked" << endl;
return shared_ptr<T>(new T(p1));
}
};

int main()
{
shared_ptr<MyClass> ptr(Factory<MyClass>::Create(42));

ptr->DoIt();
}
 
A

Alf P. Steinbach

* Dave:
#include <iostream>
#include <boost/shared_ptr.hpp>

using namespace std;
using namespace boost;

// A base class
class Deleter
{
public:
Deleter() {}
virtual ~Deleter() {}
};

What's the purpose of Deleter?

// A derived class
class MyClass: public Deleter
{
public:
MyClass(int data): m_data(data) {}
virtual ~MyClass() {}

void DoIt() const
{
cout << m_data << endl;
}

private:
int m_data;
};

// A factory for objects that are constructed with 0 or 1 parameters.
template <class T>
class Factory
{
public:
static shared_ptr<T> Create()
{
cout << "Primary Factory invoked" << endl;
return shared_ptr<T>(new T());
}

template <class P1>
static shared_ptr<T> Create(P1 p1)
{
cout << "Primary Factory invoked" << endl;
return shared_ptr<T>(new T(p1));
}
};

And what's your purpose in using a factory?

Depending on your purpose there may be a better alternative.

// Here's where I don't have things right. I'd like to specialize Factory
for types derived from Deleter.
// How may I do so?

What's the purpose of that?

Anyway if you really must you have at least three options: add a
template parameter that you can use for partial specialization, or use a
derived class, or let the general implementation defer to a specific
implementation if one exists.
 
M

mlimber

Dave said:
Hello all,

Please see my question embedded in comment form below.

Thanks,
Dave

#include <iostream>
#include <boost/shared_ptr.hpp>

using namespace std;
using namespace boost;

// A base class
class Deleter
{
public:
Deleter() {}
virtual ~Deleter() {}
};

// A derived class
class MyClass: public Deleter
{
public:
MyClass(int data): m_data(data) {}
virtual ~MyClass() {}

void DoIt() const
{
cout << m_data << endl;
}

private:
int m_data;
};

// A factory for objects that are constructed with 0 or 1 parameters.
template <class T>
class Factory
{
public:
static shared_ptr<T> Create()
{
cout << "Primary Factory invoked" << endl;
return shared_ptr<T>(new T());
}

template <class P1>
static shared_ptr<T> Create(P1 p1)
{
cout << "Primary Factory invoked" << endl;
return shared_ptr<T>(new T(p1));
}
};

// Here's where I don't have things right. I'd like to specialize Factory
for types derived from Deleter.
// How may I do so?
template <class T> // ?????????????
class Factory<Deleter> // ?????????????
{
static shared_ptr<T> Create()
{
cout << "Specialized Factory invoked" << endl;
return shared_ptr<T>(new T());
}

template <class P1>
static shared_ptr<T> Create(P1 p1)
{
cout << "Specialized Factory invoked" << endl;
return shared_ptr<T>(new T(p1));
}
};

int main()
{
shared_ptr<MyClass> ptr(Factory<MyClass>::Create(42));

ptr->DoIt();
}

To get the effect you want, put a compile-time check for inheritance
from Deleter in your Create() functions. Using Boost Typetraits and
static asserts, it would look something like:

static shared_ptr<T> Create()
{
BOOST_ASSERT( (is_base_of<Deleter, T>::value) );
// ...
}

Note the extra set of parentheses to overcome the preprocessor's
ignorance of templates. Using this code, you'd get a compile-time error
if T is not derived from Deleter.

Cheers! --M
 
D

Dave

mlimber said:
To get the effect you want, put a compile-time check for inheritance
from Deleter in your Create() functions. Using Boost Typetraits and
static asserts, it would look something like:

static shared_ptr<T> Create()
{
BOOST_ASSERT( (is_base_of<Deleter, T>::value) );
// ...
}

Note the extra set of parentheses to overcome the preprocessor's
ignorance of templates. Using this code, you'd get a compile-time error
if T is not derived from Deleter.

But I don't want a compile-time error if T is not derived from Deleter. In
that case, I would just want the primary Factory template to be used rather
than the specialization.
 
M

mlimber

Dave said:
But I don't want a compile-time error if T is not derived from Deleter. In
that case, I would just want the primary Factory template to be used rather
than the specialization.

Sorry. I didn't read it closely enough. Just use the compile-time
constant is_base_of<Deleter, T>::value to select an implementation.
Something like:

template<class T>
struct DefaultFactory
{
static shared_ptr<T> Create() { /*...*/ }
// ...
};

template<class T>
struct SpecialFactory
{
static shared_ptr<T> Create() { /*...*/ }
// ...
};

template<bool IsSpecial, class T> struct FactorySelector;

template<class T>
struct FactorySelector<true,T>
{
typedef SpecialFactory<T> Factory;
};

template<class T>
struct FactorySelector<false,T>
{
typedef DefaultFactory<T> Factory;
};

template<class T>
struct Factory
: public FactorySelector<
is_base_of<Deleter, T>::value, T >::Factory
{};


Cheers! --M
 
D

Dave

mlimber said:
Sorry. I didn't read it closely enough. Just use the compile-time
constant is_base_of<Deleter, T>::value to select an implementation.
Something like:

template<class T>
struct DefaultFactory
{
static shared_ptr<T> Create() { /*...*/ }
// ...
};

template<class T>
struct SpecialFactory
{
static shared_ptr<T> Create() { /*...*/ }
// ...
};

template<bool IsSpecial, class T> struct FactorySelector;

template<class T>
struct FactorySelector<true,T>
{
typedef SpecialFactory<T> Factory;
};

template<class T>
struct FactorySelector<false,T>
{
typedef DefaultFactory<T> Factory;
};

template<class T>
struct Factory
: public FactorySelector<
is_base_of<Deleter, T>::value, T >::Factory
{};


Cheers! --M

Hopefully the last question...

Has is_base_of<> been replaced? I cannot find it for the life of me...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top