Partial Specialization Method

Discussion in 'C++' started by MathStuf, May 6, 2007.

  1. MathStuf

    MathStuf Guest

    I have a matrix class and I would like to add a method that is only
    applicable when the template type is a of another class. How can I
    specialize the class to allow for the new method and hide it with any
    other type?

    template<class T> class Matrix
    {
    public:
    Matrix();
    Matrix(Ini
    &ini); // Only
    applicable with MyClass
    Matrix(unsigned w, unsigned h, T &d = T());

    void ImportIni(Ini
    &ini); // Only applicable
    with MyClass
    void ExportIni(std::eek:fstream &fout, const String &val);// Only
    applicable with MyClass

    void AddRow(T &d = T());
    void AddCol(T &d = T());
    bool InsertRow(unsigned pos, T &d = T());
    bool InsertCol(unsigned pos, T &d = T());
    bool DeleteRow(unsigned pos);
    bool DeleteCol(unsigned pos);

    bool Set(unsigned row, unsigned col, T &s);

    T Get(unsigned row, unsigned col);
    std::vector<T> GetRow(unsigned row);
    std::vector<T> GetCol(unsigned col);
    unsigned GetHeight();
    unsigned GetWidth();

    T operator[](Point &p);
    std::vector<T> operator[](int col);
    private:
    std::vector< std::vector<T> > matrix;
    unsigned height;
    unsigned width;
    };
    MathStuf, May 6, 2007
    #1
    1. Advertising

  2. On Sun, 06 May 2007 09:11:10 -0700, MathStuf wrote:

    > I have a matrix class and I would like to add a method that is only
    > applicable when the template type is a of another class. How can I
    > specialize the class to allow for the new method and hide it with any
    > other type?
    >
    > template<class T> class Matrix
    > {
    > public:
    > Matrix();
    > Matrix(Ini
    > &ini); // Only
    > applicable with MyClass
    > Matrix(unsigned w, unsigned h, T &d = T());


    It is illegal to bind a rvalue to a non-const reference. Make this a
    const T & if possible.

    > void ImportIni(Ini
    > &ini); // Only applicable
    > with MyClass
    > void ExportIni(std::eek:fstream &fout, const String &val);// Only
    > applicable with MyClass
    >
    > void AddRow(T &d = T());
    > void AddCol(T &d = T());
    > bool InsertRow(unsigned pos, T &d = T()); bool InsertCol(unsigned
    > pos, T &d = T()); bool DeleteRow(unsigned pos);
    > bool DeleteCol(unsigned pos);
    >
    > bool Set(unsigned row, unsigned col, T &s);
    >
    > T Get(unsigned row, unsigned col);
    > std::vector<T> GetRow(unsigned row);
    > std::vector<T> GetCol(unsigned col);
    > unsigned GetHeight();
    > unsigned GetWidth();
    >
    > T operator[](Point &p);
    > std::vector<T> operator[](int col);
    > private:
    > std::vector< std::vector<T> > matrix; unsigned height;
    > unsigned width;
    > };


    You can do it with template specialization, like so:

    template<class T> struct Base
    {
    // all common stuff from above
    // ...
    };

    template<class T> struct Matrix : Base<T>
    {
    Matrix();
    Matrix(unsigned w, unsigned h);
    };

    class MyClass;
    class Ini;

    template<> struct Matrix<MyClass> : Base<MyClass>
    {
    Matrix();
    Matrix(unsigned w, unsigned h);

    // additional stuff
    Matrix(Ini &ini);
    // ...
    };


    There is some unavoidable duplication for the constructors unfortunately.

    --
    Markus
    Markus Schoder, May 6, 2007
    #2
    1. Advertising

  3. MathStuf

    MathStuf Guest

    On May 6, 12:56 pm, Markus Schoder <> wrote:
    > On Sun, 06 May 2007 09:11:10 -0700, MathStuf wrote:
    > > I have a matrix class and I would like to add a method that is only
    > > applicable when the template type is a of another class. How can I
    > > specialize the class to allow for the new method and hide it with any
    > > other type?

    >
    > > template<class T> class Matrix
    > > {
    > > public:
    > > Matrix();
    > > Matrix(Ini
    > > &ini); // Only
    > > applicable with MyClass
    > > Matrix(unsigned w, unsigned h, T &d = T());

    >
    > It is illegal to bind a rvalue to a non-const reference. Make this a
    > const T & if possible.
    >
    >
    >
    > > void ImportIni(Ini
    > > &ini); // Only applicable
    > > with MyClass
    > > void ExportIni(std::eek:fstream &fout, const String &val);// Only
    > > applicable with MyClass

    >
    > > void AddRow(T &d = T());
    > > void AddCol(T &d = T());
    > > bool InsertRow(unsigned pos, T &d = T()); bool InsertCol(unsigned
    > > pos, T &d = T()); bool DeleteRow(unsigned pos);
    > > bool DeleteCol(unsigned pos);

    >
    > > bool Set(unsigned row, unsigned col, T &s);

    >
    > > T Get(unsigned row, unsigned col);
    > > std::vector<T> GetRow(unsigned row);
    > > std::vector<T> GetCol(unsigned col);
    > > unsigned GetHeight();
    > > unsigned GetWidth();

    >
    > > T operator[](Point &p);
    > > std::vector<T> operator[](int col);
    > > private:
    > > std::vector< std::vector<T> > matrix; unsigned height;
    > > unsigned width;
    > > };

    >
    > You can do it with template specialization, like so:
    >
    > template<class T> struct Base
    > {
    > // all common stuff from above
    > // ...
    >
    > };
    >
    > template<class T> struct Matrix : Base<T>
    > {
    > Matrix();
    > Matrix(unsigned w, unsigned h);
    >
    > };
    >
    > class MyClass;
    > class Ini;
    >
    > template<> struct Matrix<MyClass> : Base<MyClass>
    > {
    > Matrix();
    > Matrix(unsigned w, unsigned h);
    >
    > // additional stuff
    > Matrix(Ini &ini);
    > // ...
    >
    > };
    >
    > There is some unavoidable duplication for the constructors unfortunately.
    >
    > --
    > Markus


    Would it just be easier to make methods that throw() for the other
    types then?

    --MathStuf
    MathStuf, May 6, 2007
    #3
  4. On Sun, 06 May 2007 10:01:57 -0700, MathStuf wrote:
    > On May 6, 12:56 pm, Markus Schoder <> wrote:
    >> On Sun, 06 May 2007 09:11:10 -0700, MathStuf wrote:
    >> > I have a matrix class and I would like to add a method that is only
    >> > applicable when the template type is a of another class. How can I
    >> > specialize the class to allow for the new method and hide it with any
    >> > other type?

    >>
    >> > template<class T> class Matrix
    >> > {
    >> > public:
    >> > Matrix();
    >> > Matrix(Ini
    >> > &ini); // Only
    >> > applicable with MyClass
    >> > Matrix(unsigned w, unsigned h, T &d = T());

    >>
    >> It is illegal to bind a rvalue to a non-const reference. Make this a
    >> const T & if possible.
    >>
    >>
    >>
    >> > void ImportIni(Ini
    >> > &ini); // Only applicable
    >> > with MyClass
    >> > void ExportIni(std::eek:fstream &fout, const String &val);// Only
    >> > applicable with MyClass

    >>
    >> > void AddRow(T &d = T());
    >> > void AddCol(T &d = T());
    >> > bool InsertRow(unsigned pos, T &d = T()); bool
    >> > InsertCol(unsigned pos, T &d = T()); bool DeleteRow(unsigned
    >> > pos); bool DeleteCol(unsigned pos);

    >>
    >> > bool Set(unsigned row, unsigned col, T &s);

    >>
    >> > T Get(unsigned row, unsigned col);
    >> > std::vector<T> GetRow(unsigned row);
    >> > std::vector<T> GetCol(unsigned col);
    >> > unsigned GetHeight();
    >> > unsigned GetWidth();

    >>
    >> > T operator[](Point &p);
    >> > std::vector<T> operator[](int col);
    >> > private:
    >> > std::vector< std::vector<T> > matrix; unsigned height; unsigned
    >> > width;
    >> > };

    >>
    >> You can do it with template specialization, like so:
    >>
    >> template<class T> struct Base
    >> {
    >> // all common stuff from above
    >> // ...
    >>
    >> };
    >>
    >> template<class T> struct Matrix : Base<T> {
    >> Matrix();
    >> Matrix(unsigned w, unsigned h);
    >>
    >> };
    >>
    >> class MyClass;
    >> class Ini;
    >>
    >> template<> struct Matrix<MyClass> : Base<MyClass> {
    >> Matrix();
    >> Matrix(unsigned w, unsigned h);
    >>
    >> // additional stuff
    >> Matrix(Ini &ini);
    >> // ...
    >>
    >> };
    >>
    >> There is some unavoidable duplication for the constructors
    >> unfortunately.
    >>
    >> --
    >> Markus

    >
    > Would it just be easier to make methods that throw() for the other types
    > then?


    Yes probably, but I would rather not implement these methods for the
    other types at all or even better use a compile time assertion. That way
    the linker resp. compiler will tell you if someone tries to use these
    methods with the wrong class.

    --
    Markus
    Markus Schoder, May 6, 2007
    #4
  5. "MathStuf" <> wrote in message
    news:...
    >I have a matrix class and I would like to add a method that is only
    > applicable when the template type is a of another class. How can I
    > specialize the class to allow for the new method and hide it with any
    > other type?
    >
    > template<class T> class Matrix
    > {
    > public:
    > Matrix();
    > Matrix(Ini
    > &ini); // Only
    > applicable with MyClass
    > Matrix(unsigned w, unsigned h, T &d = T());
    >
    > void ImportIni(Ini
    > &ini); // Only applicable
    > with MyClass
    > void ExportIni(std::eek:fstream &fout, const String &val);// Only
    > applicable with MyClass
    >
    > void AddRow(T &d = T());
    > void AddCol(T &d = T());
    > bool InsertRow(unsigned pos, T &d = T());
    > bool InsertCol(unsigned pos, T &d = T());
    > bool DeleteRow(unsigned pos);
    > bool DeleteCol(unsigned pos);
    >
    > bool Set(unsigned row, unsigned col, T &s);
    >
    > T Get(unsigned row, unsigned col);
    > std::vector<T> GetRow(unsigned row);
    > std::vector<T> GetCol(unsigned col);
    > unsigned GetHeight();
    > unsigned GetWidth();
    >
    > T operator[](Point &p);
    > std::vector<T> operator[](int col);
    > private:
    > std::vector< std::vector<T> > matrix;
    > unsigned height;
    > unsigned width;
    > };
    >


    You can use SFINAE

    template<class T> class Matrix
    {
    public:
    /* ... */
    template<class U>
    Matrix(U yourIntParam,
    typename enable_if_c<
    is_same<T,MyClass>::value &&
    is_convertible<U,int>::value
    , int>::type = 0);
    };

    Now that constructor will only be considered by the compiler if T is MyClass
    (and if the passed U is convertible to int, which, alas, is the downside for
    making the constructor itself a template, as that is needed for SFINAE to be
    able to work). Definitions of enable_if_c<>, is_same<> and is_convertible<>
    can be found in boost, but I'll provide them here for completeness' sake.

    template<bool B, class T> struct enable_if_c { };
    template<class T> struct enable_if_c<true, T> { typedef T type; };

    template<class T, class U> struct is_same { static const bool value =
    false; };
    template<class T> struct is_same<T,T> { static const bool value = true; };

    template<class T, class U> struct is_convertible
    {
    private:
    struct small { char c; };
    struct large { char c[2]; };
    static small foo(const U & u);
    static large foo(...);
    public:
    static const bool value = (sizeof(foo(*(T*)1)) == sizeof(small));
    };

    - Sylvester Hesp
    Sylvester Hesp, May 7, 2007
    #5
    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. Chandra Shekhar Kumar

    template partial specialization

    Chandra Shekhar Kumar, Jun 24, 2003, in forum: C++
    Replies:
    17
    Views:
    3,015
    tom_usenet
    Jun 25, 2003
  2. Philip Lawatsch

    Partial Specialization workaround

    Philip Lawatsch, Jul 16, 2003, in forum: C++
    Replies:
    9
    Views:
    385
    Philip Lawatsch
    Jul 16, 2003
  3. __PPS__
    Replies:
    5
    Views:
    615
  4. Joseph Turian
    Replies:
    2
    Views:
    455
  5. vj
    Replies:
    1
    Views:
    473
Loading...

Share This Page