Re: is there a way to do this in C++?

Discussion in 'C++' started by Jerry Coffin, Aug 9, 2009.

  1. Jerry Coffin

    Jerry Coffin Guest

    In article <f53ee742-bdd4-4226-b436-315a4745f709
    @z34g2000vbl.googlegroups.com>, says...
    >
    > Hi,
    >
    > I was wondering if it is possible to do the following trick in C++:
    > let's say you have a class template the represents a multi-dimensional
    > array:
    >
    > template <int d, typename T = double>
    > class Array {
    >
    > // rest of the class
    >
    > };
    >
    > Now, you would like to have different interfaces depending on the
    > dimension of the array. For example, if I have Array <2,T> we have a
    > matrix and it may be convenient to have functions "rows()" and "columns
    > ()", which of course don't make sense for Array<1,T>.
    > I would like to know if there is a way to change the interface of the
    > Array class WITHOUT having to inherit from another class. I was
    > thinking of some kind of template function defined in the body of the
    > Array class but is defined ONLY if you're instantiating Array<2,T>.


    Partial specialization is what you seem to need/want:

    #include <cstddef>

    // The base template
    template <int d, typename T = double>
    class Array {
    T *data;
    int dimensions;
    public:
    Array() : data(NULL), dimensions(d) {}
    };

    // A partial specialization for 2 dimensional Array's.
    template <typename T>
    class Array<2, T> {
    T *data;
    int dimensions;
    int rows_, columns_;

    public:
    Array(int r, int c)
    : data(NULL), dimensions(2), rows_(r), columns_(c)
    {}

    int rows() { return rows_; }
    int columns() { return columns_; }
    };

    #ifdef TEST
    #include <iostream>

    int main() {

    Array<1> vect;
    Array<2, double> matrix(2, 3);

    std::cout << matrix.rows();

    // This won't compile -- Array<1, double>::rows doesn't exist.
    // std::cout << vect.rows();
    return 0;
    }

    #endif

    --
    Later,
    Jerry.
    Jerry Coffin, Aug 9, 2009
    #1
    1. Advertising

  2. Jerry Coffin

    Jerry Coffin Guest

    In article <b332afc2-44c3-41e0-9926-74c2b3be1177
    @e34g2000vbm.googlegroups.com>, says...

    [ ... ]

    > Thanks for the responses. I actually don't want a template
    > specialization. If I wanted it I would write a Vector class and a
    > Matrix class and so on. I want the code to be very generic and I
    > thought there was some kind of trick to define an interface based on a
    > boolean constant (d == 2) at compilation time. All without having to
    > inherit from a base class. I could use the policy based design
    > approach and inherit from a base class to provide additional
    > functionality to the class, but I wanted to avoid this path.


    You've ruled out using a single class (inheritance) and you've ruled
    out separate classes. If one class doesn't work and separate classes
    don't work, I'm a bit lost as to what you want.

    --
    Later,
    Jerry.
    Jerry Coffin, Aug 10, 2009
    #2
    1. Advertising

  3. Jerry Coffin

    James Kanze Guest

    On Aug 10, 12:42 am, Jerry Coffin <> wrote:
    > In article <f53ee742-bdd4-4226-b436-315a4745f709
    > @z34g2000vbl.googlegroups.com>, says...
    > > I was wondering if it is possible to do the following trick
    > > in C++: let's say you have a class template the represents a
    > > multi-dimensional array:


    > > template <int d, typename T = double>
    > > class Array {


    > > // rest of the class


    > > };


    > > Now, you would like to have different interfaces depending
    > > on the dimension of the array. For example, if I have Array
    > > <2,T> we have a matrix and it may be convenient to have
    > > functions "rows()" and "columns ()", which of course don't
    > > make sense for Array<1,T>. I would like to know if there is
    > > a way to change the interface of the Array class WITHOUT
    > > having to inherit from another class. I was thinking of some
    > > kind of template function defined in the body of the Array
    > > class but is defined ONLY if you're instantiating
    > > Array<2,T>.


    > Partial specialization is what you seem to need/want:


    > #include <cstddef>


    > // The base template
    > template <int d, typename T = double>
    > class Array {
    > T *data;
    > int dimensions;
    > public:
    > Array() : data(NULL), dimensions(d) {}
    > };


    > // A partial specialization for 2 dimensional Array's.
    > template <typename T>
    > class Array<2, T> {
    > T *data;
    > int dimensions;
    > int rows_, columns_;


    > public:
    > Array(int r, int c)
    > : data(NULL), dimensions(2), rows_(r), columns_(c)
    > {}


    > int rows() { return rows_; }
    > int columns() { return columns_; }
    > };


    If I understand correctly, you're proposing a partial
    specialization for each possible dimension. I think it should
    be possible to implement with a partial specialization for d ==
    1, and a generic specialization with Array<n> implemented in
    terms of Array<n-1>. Something like:

    template< size_t d, typename T = double >
    class Array
    {
    std::vector< Array< d - 1 > > data ;
    public:
    Array< d - 1 >& operator[]( size_t n )
    {
    return data[ n ] ;
    }
    // ...
    } ;

    template< typename T = double >
    class Array< 1, T >
    {
    std::vector< T > data ;
    public:
    T& operator[]( size_t n )
    {
    return data[ n ] ;
    }
    // ...
    } ;

    If you want to keep the fact that the data is actually in a
    single vector, then it becomes more complicated---you'd probably
    need a few helper classes. But I don't think it would be that
    difficult for someone familiar with template programming.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Aug 10, 2009
    #3
  4. Jerry Coffin

    Jerry Coffin Guest

    In article <d0fa1b12-b1bc-4dc1-b006-4fc591c89ce4
    @g19g2000vbi.googlegroups.com>, says...

    [ ... ]

    > If I understand correctly, you're proposing a partial
    > specialization for each possible dimension.


    No -- at least as he described the situation, what he wanted was some
    "special stuff" for two-dimensional Array's, and all other dimensions
    would have the same interface.

    > I think it should
    > be possible to implement with a partial specialization for d ==
    > 1, and a generic specialization with Array<n> implemented in
    > terms of Array<n-1>. Something like:


    I thought about something like that -- in fact, it seemed to make
    more sense to me, so I reread his description a couple of times just
    to be sure that the special handling was for two dimensions, and any
    fewer OR more would _not_ get the special interface.

    --
    Later,
    Jerry.
    Jerry Coffin, Aug 10, 2009
    #4
  5. Jerry Coffin

    SG Guest

    On 10 Aug., 02:12, aaragon <> wrote:
    >
    > Thanks for the responses. I actually don't want a template
    > specialization. If I wanted it I would write a Vector class and a
    > Matrix class and so on. I want the code to be very generic and I
    > thought there was some kind of trick to define an interface based on a
    > boolean constant (d == 2) at compilation time.


    There was actually a proposal for that: concepts. You would have been
    able to write

    template<int Dim, typename T>
    class Array {
    ...

    requires std::True<(Dim==2)>
    int columns() const;

    requires std::True<(Dim==2)>
    int rows() const;

    ...
    };

    Without derivation there's another approach left: free function
    templates:

    // to be defined in the same namespace for ADL
    template<typename T>
    inline int columns(Array<2,T> const& x)
    { /*...*/ }


    Cheers!
    SG
    SG, Aug 10, 2009
    #5
  6. Jerry Coffin

    James Kanze Guest

    On Aug 10, 4:35 pm, Jerry Coffin <> wrote:
    > In article <d0fa1b12-b1bc-4dc1-b006-4fc591c89ce4
    > @g19g2000vbi.googlegroups.com>, says...


    > [ ... ]


    > > If I understand correctly, you're proposing a partial
    > > specialization for each possible dimension.


    > No -- at least as he described the situation, what he wanted
    > was some "special stuff" for two-dimensional Array's, and all
    > other dimensions would have the same interface.


    Ah. I missed that. But how do all other dimensions have the
    same interface? If nothing else, you definitely need a
    different number of indices to access the data.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Aug 11, 2009
    #6
  7. Jerry Coffin

    SG Guest

    On 10 Aug., 17:21, aaragon <> wrote:
    > SG, the one that uses concepts is exactly what I want. It seems though
    > that it is still not implemented by the latest GCC compilers (which is
    > what I use).


    This will probably stay that way for "a while" since concepts have
    been removed from C++0x.

    > I use variadic templates to solve the problem of indexing
    > the elements using operator(), and for the constructors (so that I can
    > have a single constructor for all dimensions). However, concepts is
    > still not supported.


    Checkout Boost.MultiArray:
    http://www.boost.org/doc/libs/1_39_0/libs/multi_array/doc/user.html

    It solves indexing without variadic templates (as far as I can tell).

    > I wanted to ask you about the second approach. What I wanted is to
    > have member functions, so I guess I cannot use what you suggest.


    Right. However, if the function took an argument you could convert it
    into a template, rely on template argument deduction and "apply
    SFINAE" to block the case Dim!=2. I used this trick for a class
    template that provided a special constructor in some cases. Though, in
    retrospect, I should have used a free function template instead....

    Cheers!
    SG
    SG, Aug 11, 2009
    #7
  8. Jerry Coffin

    Jerry Coffin Guest

    In article <c7560bfa-fa41-406a-8a3c-93b85b51604e@
    26g2000yqk.googlegroups.com>, says...
    >
    > On Aug 10, 4:35 pm, Jerry Coffin <> wrote:


    [ ... ]

    > > No -- at least as he described the situation, what he wanted
    > > was some "special stuff" for two-dimensional Array's, and all
    > > other dimensions would have the same interface.

    >
    > Ah. I missed that. But how do all other dimensions have the
    > same interface? If nothing else, you definitely need a
    > different number of indices to access the data.


    I can only hope the OP will contribute an answer -- I was wondering
    myself, but his post seemed quite clear anyway.

    --
    Later,
    Jerry.
    Jerry Coffin, Aug 11, 2009
    #8
    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. Replies:
    4
    Views:
    374
    Branimir Maksimovic
    Oct 20, 2005
  2. Paul Rubin
    Replies:
    5
    Views:
    416
    Hendrik van Rooyen
    Aug 6, 2009
  3. Bill Nicholson
    Replies:
    1
    Views:
    133
    Phil H
    Sep 26, 2007
  4. Andries

    is there a way ..... any way

    Andries, Apr 26, 2004, in forum: Perl Misc
    Replies:
    27
    Views:
    246
    Robin
    Apr 27, 2004
  5. francisco lopez
    Replies:
    2
    Views:
    166
    Dr John Stockton
    Dec 31, 2004
Loading...

Share This Page