Class templates and singleton container

Discussion in 'C++' started by Bit Byter, Nov 1, 2008.

  1. Bit Byter

    Bit Byter Guest

    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?
     
    Bit Byter, Nov 1, 2008
    #1
    1. Advertising

  2. Bit Byter

    Francesco Guest

    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
     
    Francesco, Nov 3, 2008
    #2
    1. Advertising

  3. Bit Byter

    Francesco Guest

    (2b|!2b)==? ha scritto:

    > Francesco wrote:
    > >
    > > 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
     
    Francesco, Nov 4, 2008
    #3
  4. Bit Byter

    Francesco Guest

    (2b|!2b)==? ha scritto:

    > Francesco wrote:
    > >
    > > 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
     
    Francesco, Nov 4, 2008
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JKop
    Replies:
    3
    Views:
    506
  2. recover
    Replies:
    2
    Views:
    845
    recover
    Jul 25, 2006
  3. Wilhelm
    Replies:
    1
    Views:
    181
  4. Paul McMahon
    Replies:
    3
    Views:
    217
    David A. Black
    Jun 9, 2008
  5. Charles Oliver Nutter

    Singleton methods without the singleton class

    Charles Oliver Nutter, Mar 15, 2010, in forum: Ruby
    Replies:
    4
    Views:
    216
    Charles Oliver Nutter
    Mar 22, 2010
Loading...

Share This Page