Class templates and singleton container

B

Bit Byter

I want to write a (singleton) container for instances of my class
templates, however, I am not too sure on how to:

1). Store the instances
2). How to write the acccesor method (instance()) to retrieve an
instance of particular template
3). What type to return an instance as ..

Assuming I have the following code:

class template

template <class T1, class T2>
class MyTree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};


// Notes
// Instance prototype not completed (see question 2 and 3)
// Ideally, when an instance of a particular class is requested, if it
dosen't yet exist, then an
// instance is created and stored in the 'repository'
class Container
{
instance();
};


//Main.cpp

int main(int argc, char* argv[])
{
Container c;

MyTree<double, int> * t1 = c.instance(/*some args here*/);
MyTree<string, double> *t2 = c.instance(/*some args here*/);

}


Last but not the least, I want to be able to treat objects returned by
the instance() method, in a generic way (i.e. in this example, I want
to be able to treat them generically, as trees). Should I use
inheritance (i.e. the class template inherits from a base Tree class)
like this:

template <class T1, class T2>
class MyTree : public Tree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};

or is there a better way?
 
F

Francesco

Bit Byter ha scritto:
I want to write a (singleton) container for instances of my class
templates, however, I am not too sure on how to:

1). Store the instances
2). How to write the acccesor method (instance()) to retrieve an
instance of particular template
3). What type to return an instance as ..

Assuming I have the following code:

class template

template <class T1, class T2>
class MyTree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};


// Notes
// Instance prototype not completed (see question 2 and 3)
// Ideally, when an instance of a particular class is requested, if it
dosen't yet exist, then an
// instance is created and stored in the 'repository'
class Container
{
instance();
};


//Main.cpp

int main(int argc, char* argv[])
{
Container c;

MyTree<double, int> * t1 = c.instance(/*some args here*/);
MyTree<string, double> *t2 = c.instance(/*some args here*/);

}


Last but not the least, I want to be able to treat objects returned by
the instance() method, in a generic way (i.e. in this example, I want
to be able to treat them generically, as trees). Should I use
inheritance (i.e. the class template inherits from a base Tree class)
like this:

template <class T1, class T2>
class MyTree : public Tree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};

or is there a better way?

Hi,
I don't know exactly what you want to do, so there might be better
solutions...
But they way you've put it, I guess using something like boost::any
should do what
you want. Check the code below.
Hope it helps a little.
Bye,
Francesco

#include <vector>

#include <boost/any.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <iostream>

using namespace boost;

//------------------------------------------------------------

class CObjBase
{
public:

virtual ~CObjBase() {}

virtual any DoSome( any const & ) = 0;

virtual any DoOther( any const & inArg1,
any const & inArg2 ) = 0;

virtual bool IsOfType( std::type_info const *,
std::type_info const * ) = 0;
};
//------------------------------------------------------------

template< typename T1, typename T2 >
class CObjConcrete : public CObjBase
{
public:

any DoSome( any const & inArg1 )
{
T2 obj = any_cast< T2 >( inArg1 ); // use object
std::cout << "-------\n";
std::cout << "Arg1: " << obj << std::endl;
return T1(); // return whatever;
}

any DoOther( any const & inArg1, any const & inArg2 )
{
T1 obj1 = any_cast< T1 >( inArg1 );
T2 obj2 = any_cast< T2 >( inArg2 );
std::cout << "-------\n";
std::cout << "Arg1 : " << obj1 << std::endl;
std::cout << "Arg2 : " << obj2 << std::endl;
return obj2;
}

bool IsOfType( std::type_info const * inT1Ptr,
std::type_info const * inT2Ptr )
{
if( *inT1Ptr == typeid( T1 ) and *inT2Ptr == typeid( T2 ) )
return true;
else
return false;
}
};

//------------------------------------------------------------

class CFactory
{
public:
static CFactory & GetInstance()
{ static CFactory sObj; return sObj; }

template< typename T1, typename T2 >
shared_ptr< CObjBase > Get();

private:

typedef std::vector< shared_ptr< CObjBase > > CRegister;

CRegister mRegister;

CFactory() {}
CFactory( CFactory const & );
~CFactory() {}
CFactory & operator=( CFactory const & );
};

CFactory & Factory() { return CFactory::GetInstance(); }

//------------------------------------------------------------

template< typename T1, typename T2 >
shared_ptr< CObjBase > CFactory::Get()
{

CRegister::iterator iter = std::find_if(
mRegister.begin(),
mRegister.end(),
bind( &CObjBase::IsOfType, _1, &typeid( T1 ), &typeid( T2 ) )
);

if( iter == mRegister.end() )
{
std::cout << "CREATING\n";
shared_ptr< CObjBase > ptr( new CObjConcrete< T1, T2 > );
mRegister.push_back( ptr );
return ptr;
}
else
{
std::cout << "REUSING\n";
return *iter;
}
}

//------------------------------------------------------------

int main()
{
Factory().Get< int, double >()->DoSome( 13.56 );
Factory().Get< std::string, int >()->DoOther(
std::string( "ola" ),
100
);
Factory().Get< int, double >()->DoSome( 67.67 );
Factory().Get< std::string, int >()->DoOther(
std::string( "TEST" ),
900
);
std::cin.get();
}

//end code
 
F

Francesco

(2b|!2b)==? ha scritto:
Francesco said:
Bit Byter ha scritto:
I want to write a (singleton) container for instances of my class
templates, however, I am not too sure on how to:

1). Store the instances
2). How to write the acccesor method (instance()) to retrieve an
instance of particular template
3). What type to return an instance as ..

Assuming I have the following code:

class template

template <class T1, class T2>
class MyTree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};


// Notes
// Instance prototype not completed (see question 2 and 3)
// Ideally, when an instance of a particular class is requested, if it
dosen't yet exist, then an
// instance is created and stored in the 'repository'
class Container
{
instance();
};


//Main.cpp

int main(int argc, char* argv[])
{
Container c;

MyTree<double, int> * t1 = c.instance(/*some args here*/);
MyTree<string, double> *t2 = c.instance(/*some args here*/);

}


Last but not the least, I want to be able to treat objects returned by
the instance() method, in a generic way (i.e. in this example, I want
to be able to treat them generically, as trees). Should I use
inheritance (i.e. the class template inherits from a base Tree class)
like this:

template <class T1, class T2>
class MyTree : public Tree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};

or is there a better way?

Hi,
I don't know exactly what you want to do, so there might be better
solutions...
But they way you've put it, I guess using something like boost::any
should do what
you want. Check the code below.
Hope it helps a little.
Bye,
Francesco

#include <vector>

#include <boost/any.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <iostream>

using namespace boost;

//------------------------------------------------------------

class CObjBase
{
public:

virtual ~CObjBase() {}

virtual any DoSome( any const & ) = 0;

virtual any DoOther( any const & inArg1,
any const & inArg2 ) = 0;

virtual bool IsOfType( std::type_info const *,
std::type_info const * ) = 0;
};
//------------------------------------------------------------

template< typename T1, typename T2 >
class CObjConcrete : public CObjBase
{
public:

any DoSome( any const & inArg1 )
{
T2 obj = any_cast< T2 >( inArg1 ); // use object
std::cout << "-------\n";
std::cout << "Arg1: " << obj << std::endl;
return T1(); // return whatever;
}

any DoOther( any const & inArg1, any const & inArg2 )
{
T1 obj1 = any_cast< T1 >( inArg1 );
T2 obj2 = any_cast< T2 >( inArg2 );
std::cout << "-------\n";
std::cout << "Arg1 : " << obj1 << std::endl;
std::cout << "Arg2 : " << obj2 << std::endl;
return obj2;
}

bool IsOfType( std::type_info const * inT1Ptr,
std::type_info const * inT2Ptr )
{
if( *inT1Ptr == typeid( T1 ) and *inT2Ptr == typeid( T2 ) )
return true;
else
return false;
}
};

//------------------------------------------------------------

class CFactory
{
public:
static CFactory & GetInstance()
{ static CFactory sObj; return sObj; }

template< typename T1, typename T2 >
shared_ptr< CObjBase > Get();

private:

typedef std::vector< shared_ptr< CObjBase > > CRegister;

CRegister mRegister;

CFactory() {}
CFactory( CFactory const & );
~CFactory() {}
CFactory & operator=( CFactory const & );
};

CFactory & Factory() { return CFactory::GetInstance(); }

//------------------------------------------------------------

template< typename T1, typename T2 >
shared_ptr< CObjBase > CFactory::Get()
{

CRegister::iterator iter = std::find_if(
mRegister.begin(),
mRegister.end(),
bind( &CObjBase::IsOfType, _1, &typeid( T1 ), &typeid( T2 ) )
);

if( iter == mRegister.end() )
{
std::cout << "CREATING\n";
shared_ptr< CObjBase > ptr( new CObjConcrete< T1, T2 > );
mRegister.push_back( ptr );
return ptr;
}
else
{
std::cout << "REUSING\n";
return *iter;
}
}

//------------------------------------------------------------

int main()
{
Factory().Get< int, double >()->DoSome( 13.56 );
Factory().Get< std::string, int >()->DoOther(
std::string( "ola" ),
100
);
Factory().Get< int, double >()->DoSome( 67.67 );
Factory().Get< std::string, int >()->DoOther(
std::string( "TEST" ),
900
);
std::cin.get();
}

//end code

Thanks Francesco,

This is exactly what I was looking for. I have a quick question about
your IsOfType function:

bool IsOfType( std::type_info const * inT1Ptr,
std::type_info const * inT2Ptr )
{
if( *inT1Ptr == typeid( T1 ) and *inT2Ptr == typeid( T2 ) )
return true;
else
return false;
}

You are using 'and' is that in the boost namespace? (I couldnt find it),
or did you simply mean the unary boolean 'and' operator (&&) ?

No, it's not boost stuff, it's standard: just an alternative token to
&&. Check out the standard @ "2.5 Alternative Tokens"...
I believe it's a binary op though... ;-)
Glad I helped, bye,
Francesco
 
F

Francesco

(2b|!2b)==? ha scritto:
Francesco said:
Bit Byter ha scritto:
I want to write a (singleton) container for instances of my class
templates, however, I am not too sure on how to:

1). Store the instances
2). How to write the acccesor method (instance()) to retrieve an
instance of particular template
3). What type to return an instance as ..

Assuming I have the following code:

class template

template <class T1, class T2>
class MyTree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};


// Notes
// Instance prototype not completed (see question 2 and 3)
// Ideally, when an instance of a particular class is requested, if it
dosen't yet exist, then an
// instance is created and stored in the 'repository'
class Container
{
instance();
};


//Main.cpp

int main(int argc, char* argv[])
{
Container c;

MyTree<double, int> * t1 = c.instance(/*some args here*/);
MyTree<string, double> *t2 = c.instance(/*some args here*/);

}


Last but not the least, I want to be able to treat objects returned by
the instance() method, in a generic way (i.e. in this example, I want
to be able to treat them generically, as trees). Should I use
inheritance (i.e. the class template inherits from a base Tree class)
like this:

template <class T1, class T2>
class MyTree : public Tree
{
T1 foo(const T2& a1);
T2 foobar(const T1& a1, const T2& a2);
};

or is there a better way?

Hi,
I don't know exactly what you want to do, so there might be better
solutions...
But they way you've put it, I guess using something like boost::any
should do what
you want. Check the code below.
Hope it helps a little.
Bye,
Francesco

#include <vector>

#include <boost/any.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <iostream>

using namespace boost;

//------------------------------------------------------------

class CObjBase
{
public:

virtual ~CObjBase() {}

virtual any DoSome( any const & ) = 0;

virtual any DoOther( any const & inArg1,
any const & inArg2 ) = 0;

virtual bool IsOfType( std::type_info const *,
std::type_info const * ) = 0;
};
//------------------------------------------------------------

template< typename T1, typename T2 >
class CObjConcrete : public CObjBase
{
public:

any DoSome( any const & inArg1 )
{
T2 obj = any_cast< T2 >( inArg1 ); // use object
std::cout << "-------\n";
std::cout << "Arg1: " << obj << std::endl;
return T1(); // return whatever;
}

any DoOther( any const & inArg1, any const & inArg2 )
{
T1 obj1 = any_cast< T1 >( inArg1 );
T2 obj2 = any_cast< T2 >( inArg2 );
std::cout << "-------\n";
std::cout << "Arg1 : " << obj1 << std::endl;
std::cout << "Arg2 : " << obj2 << std::endl;
return obj2;
}

bool IsOfType( std::type_info const * inT1Ptr,
std::type_info const * inT2Ptr )
{
if( *inT1Ptr == typeid( T1 ) and *inT2Ptr == typeid( T2 ) )
return true;
else
return false;
}
};

//------------------------------------------------------------

class CFactory
{
public:
static CFactory & GetInstance()
{ static CFactory sObj; return sObj; }

template< typename T1, typename T2 >
shared_ptr< CObjBase > Get();

private:

typedef std::vector< shared_ptr< CObjBase > > CRegister;

CRegister mRegister;

CFactory() {}
CFactory( CFactory const & );
~CFactory() {}
CFactory & operator=( CFactory const & );
};

CFactory & Factory() { return CFactory::GetInstance(); }

//------------------------------------------------------------

template< typename T1, typename T2 >
shared_ptr< CObjBase > CFactory::Get()
{

CRegister::iterator iter = std::find_if(
mRegister.begin(),
mRegister.end(),
bind( &CObjBase::IsOfType, _1, &typeid( T1 ), &typeid( T2 ) )
);

if( iter == mRegister.end() )
{
std::cout << "CREATING\n";
shared_ptr< CObjBase > ptr( new CObjConcrete< T1, T2 > );
mRegister.push_back( ptr );
return ptr;
}
else
{
std::cout << "REUSING\n";
return *iter;
}
}

//------------------------------------------------------------

int main()
{
Factory().Get< int, double >()->DoSome( 13.56 );
Factory().Get< std::string, int >()->DoOther(
std::string( "ola" ),
100
);
Factory().Get< int, double >()->DoSome( 67.67 );
Factory().Get< std::string, int >()->DoOther(
std::string( "TEST" ),
900
);
std::cin.get();
}

//end code

Thanks Francesco,

This is exactly what I was looking for. I have a quick question about
your IsOfType function:

bool IsOfType( std::type_info const * inT1Ptr,
std::type_info const * inT2Ptr )
{
if( *inT1Ptr == typeid( T1 ) and *inT2Ptr == typeid( T2 ) )
return true;
else
return false;
}

You are using 'and' is that in the boost namespace? (I couldnt find it),
or did you simply mean the unary boolean 'and' operator (&&) ?

[this might be a double post... sorry in advance]

Anyway, no 'and' is not boost stuff, it's standard c++: it's just an
alternative token to &&.
Check out the standard @ "2.5 Alternative tokens".
I believe it's a binary op though... ;-)
Glad I helped, bye,
Francesco
 

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

Forum statistics

Threads
474,262
Messages
2,571,052
Members
48,769
Latest member
Clifft

Latest Threads

Top