Factory specialization

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dave

    #1

    Factory specialization

    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>(n ew T());
    }

    template <class P1>
    static shared_ptr<T> Create(P1 p1)
    {
    cout << "Primary Factory invoked" << endl;
    return shared_ptr<T>(n ew 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 << "Specialize d Factory invoked" << endl;
    return shared_ptr<T>(n ew T());
    }

    template <class P1>
    static shared_ptr<T> Create(P1 p1)
    {
    cout << "Specialize d Factory invoked" << endl;
    return shared_ptr<T>(n ew T(p1));
    }
    };

    int main()
    {
    shared_ptr<MyCl ass> ptr(Factory<MyC lass>::Create(4 2));

    ptr->DoIt();
    }


  • Alf P. Steinbach

    #2
    Re: Factory specialization

    * Dave:[color=blue]
    >
    > #include <iostream>
    > #include <boost/shared_ptr.hpp>
    >
    > using namespace std;
    > using namespace boost;
    >
    > // A base class
    > class Deleter
    > {
    > public:
    > Deleter() {}
    > virtual ~Deleter() {}
    > };[/color]

    What's the purpose of Deleter?

    [color=blue]
    > // 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>(n ew T());
    > }
    >
    > template <class P1>
    > static shared_ptr<T> Create(P1 p1)
    > {
    > cout << "Primary Factory invoked" << endl;
    > return shared_ptr<T>(n ew T(p1));
    > }
    > };[/color]

    And what's your purpose in using a factory?

    Depending on your purpose there may be a better alternative.

    [color=blue]
    > // 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?[/color]

    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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?

    Comment

    • mlimber

      #3
      Re: Factory specialization

      Dave wrote:[color=blue]
      > 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>(n ew T());
      > }
      >
      > template <class P1>
      > static shared_ptr<T> Create(P1 p1)
      > {
      > cout << "Primary Factory invoked" << endl;
      > return shared_ptr<T>(n ew 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 << "Specialize d Factory invoked" << endl;
      > return shared_ptr<T>(n ew T());
      > }
      >
      > template <class P1>
      > static shared_ptr<T> Create(P1 p1)
      > {
      > cout << "Specialize d Factory invoked" << endl;
      > return shared_ptr<T>(n ew T(p1));
      > }
      > };
      >
      > int main()
      > {
      > shared_ptr<MyCl ass> ptr(Factory<MyC lass>::Create(4 2));
      >
      > ptr->DoIt();
      > }[/color]

      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<Del eter, 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

      Comment

      • Dave

        #4
        Re: Factory specialization


        "mlimber" <mlimber@gmail. com> wrote in message
        news:1133379344 .708484.178350@ o13g2000cwo.goo glegroups.com.. .[color=blue]
        > Dave wrote:[color=green]
        > > 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>(n ew T());
        > > }
        > >
        > > template <class P1>
        > > static shared_ptr<T> Create(P1 p1)
        > > {
        > > cout << "Primary Factory invoked" << endl;
        > > return shared_ptr<T>(n ew T(p1));
        > > }
        > > };
        > >
        > > // Here's where I don't have things right. I'd like to specialize[/color][/color]
        Factory[color=blue][color=green]
        > > for types derived from Deleter.
        > > // How may I do so?
        > > template <class T> // ?????????????
        > > class Factory<Deleter > // ?????????????
        > > {
        > > static shared_ptr<T> Create()
        > > {
        > > cout << "Specialize d Factory invoked" << endl;
        > > return shared_ptr<T>(n ew T());
        > > }
        > >
        > > template <class P1>
        > > static shared_ptr<T> Create(P1 p1)
        > > {
        > > cout << "Specialize d Factory invoked" << endl;
        > > return shared_ptr<T>(n ew T(p1));
        > > }
        > > };
        > >
        > > int main()
        > > {
        > > shared_ptr<MyCl ass> ptr(Factory<MyC lass>::Create(4 2));
        > >
        > > ptr->DoIt();
        > > }[/color]
        >
        > 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<Del eter, 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.[/color]

        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.
        [color=blue]
        >
        > Cheers! --M
        >[/color]


        Comment

        • mlimber

          #5
          Re: Factory specialization

          Dave wrote:[color=blue]
          > "mlimber" <mlimber@gmail. com> wrote in message
          > news:1133379344 .708484.178350@ o13g2000cwo.goo glegroups.com.. .[color=green]
          > > Dave wrote:[color=darkred]
          > > > 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>(n ew T());
          > > > }
          > > >
          > > > template <class P1>
          > > > static shared_ptr<T> Create(P1 p1)
          > > > {
          > > > cout << "Primary Factory invoked" << endl;
          > > > return shared_ptr<T>(n ew T(p1));
          > > > }
          > > > };
          > > >
          > > > // Here's where I don't have things right. I'd like to specialize[/color][/color]
          > Factory[color=green][color=darkred]
          > > > for types derived from Deleter.
          > > > // How may I do so?
          > > > template <class T> // ?????????????
          > > > class Factory<Deleter > // ?????????????
          > > > {
          > > > static shared_ptr<T> Create()
          > > > {
          > > > cout << "Specialize d Factory invoked" << endl;
          > > > return shared_ptr<T>(n ew T());
          > > > }
          > > >
          > > > template <class P1>
          > > > static shared_ptr<T> Create(P1 p1)
          > > > {
          > > > cout << "Specialize d Factory invoked" << endl;
          > > > return shared_ptr<T>(n ew T(p1));
          > > > }
          > > > };
          > > >
          > > > int main()
          > > > {
          > > > shared_ptr<MyCl ass> ptr(Factory<MyC lass>::Create(4 2));
          > > >
          > > > ptr->DoIt();
          > > > }[/color]
          > >
          > > 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<Del eter, 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.[/color]
          >
          > 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.[/color]

          Sorry. I didn't read it closely enough. Just use the compile-time
          constant is_base_of<Dele ter, 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<Dele ter, T>::value, T >::Factory
          {};


          Cheers! --M

          Comment

          • Dave

            #6
            Re: Factory specialization


            "mlimber" <mlimber@gmail. com> wrote in message
            news:1133381850 .933836.206160@ g47g2000cwa.goo glegroups.com.. .[color=blue]
            > Dave wrote:[color=green]
            > > "mlimber" <mlimber@gmail. com> wrote in message
            > > news:1133379344 .708484.178350@ o13g2000cwo.goo glegroups.com.. .[color=darkred]
            > > > Dave wrote:
            > > > > 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[/color][/color][/color]
            parameters.[color=blue][color=green][color=darkred]
            > > > > template <class T>
            > > > > class Factory
            > > > > {
            > > > > public:
            > > > > static shared_ptr<T> Create()
            > > > > {
            > > > > cout << "Primary Factory invoked" << endl;
            > > > > return shared_ptr<T>(n ew T());
            > > > > }
            > > > >
            > > > > template <class P1>
            > > > > static shared_ptr<T> Create(P1 p1)
            > > > > {
            > > > > cout << "Primary Factory invoked" << endl;
            > > > > return shared_ptr<T>(n ew T(p1));
            > > > > }
            > > > > };
            > > > >
            > > > > // Here's where I don't have things right. I'd like to specialize[/color]
            > > Factory[color=darkred]
            > > > > for types derived from Deleter.
            > > > > // How may I do so?
            > > > > template <class T> // ?????????????
            > > > > class Factory<Deleter > // ?????????????
            > > > > {
            > > > > static shared_ptr<T> Create()
            > > > > {
            > > > > cout << "Specialize d Factory invoked" << endl;
            > > > > return shared_ptr<T>(n ew T());
            > > > > }
            > > > >
            > > > > template <class P1>
            > > > > static shared_ptr<T> Create(P1 p1)
            > > > > {
            > > > > cout << "Specialize d Factory invoked" << endl;
            > > > > return shared_ptr<T>(n ew T(p1));
            > > > > }
            > > > > };
            > > > >
            > > > > int main()
            > > > > {
            > > > > shared_ptr<MyCl ass> ptr(Factory<MyC lass>::Create(4 2));
            > > > >
            > > > > 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<Del eter, 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[/color][/color][/color]
            error[color=blue][color=green][color=darkred]
            > > > if T is not derived from Deleter.[/color]
            > >
            > > But I don't want a compile-time error if T is not derived from Deleter.[/color][/color]
            In[color=blue][color=green]
            > > that case, I would just want the primary Factory template to be used[/color][/color]
            rather[color=blue][color=green]
            > > than the specialization.[/color]
            >
            > Sorry. I didn't read it closely enough. Just use the compile-time
            > constant is_base_of<Dele ter, 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<Dele ter, T>::value, T >::Factory
            > {};
            >
            >
            > Cheers! --M
            >[/color]

            Hopefully the last question...

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


            Comment

            • mlimber

              #7
              Re: Factory specialization

              Dave wrote:
              [snip][color=blue]
              > Hopefully the last question...
              >
              > Has is_base_of<> been replaced? I cannot find it for the life of me...[/color]

              It's in the Boost.Typetrait s documentation:



              but it looks like it has been renamed is_base_and_der ived. Sorry about
              the confusion.

              Cheers! --M

              Comment

              Working...