Parameter List / Parameter Block / Anything patterns...

Discussion in 'C++' started by mast2as@yahoo.com, Mar 29, 2007.

  1. Guest

    Hi everyone

    I need to come up with an efficient solution to add/remove/access
    parameters to an object. Lets say I create an object "Cart" and at run
    time based on the user input, lets say we add to this "Cart" object 3
    Oranges 4 Apples and 1 Salad (stupid example I know). Whenever we do
    something with this cast object we want to be able to have access to
    all the data that it holds (3 oranges, 4 apples, 1 salad).

    in pseudo code it would do something like that

    Cart *cart = new Cart;
    Orange orange[4] = { orange1, orange2, orange3, orange4 };
    Cart.SetParameter( "SomeOrange", orange ); // copy the 4 orange in
    memory
    Orange *iterOrange = Cart.GetParameter( "SomeOrange" );
    for ( unsigned i = 0; i < 4; ++i )
    Orange *o = iterOrange;

    To get something like that to work the Cart class would have a member
    variable that would look like that.

    std::map<const char *, Data> dict;

    So a unique name is associated with each data, such that we can look
    for that parameter name later on when we call GetParameter.

    I looked a little bit on the net and found a few documents on C++
    patterns that seem to do what I need. They seem to be called Parameter
    List, Parameter Block or Anything Patterns. But I have a hard time
    making to work or find a good implementation example. It sounds like
    some API are using these patterns. I have heard of the 3DMaya API &
    the nVidia Gelato API. It is used for these 3D renderers because it
    allows to add any data of any type at run time for example to lets say
    geometric primitives (and I want to use it for that purpose).

    I am not sure what is the best way of doing that so was wondering if
    someone knows a good implementation of these patterns or could put me
    on the right track to write my own. I thought of simply doing
    something like that :

    enum ParamType { kFloat, kInt, kString };

    class Param
    {
    public:
    ParamType type;
    std::vector<float> fdefault;
    std::vector<const char *> sdefault;
    std::vector<int> idefault;
    Param() {}
    };

    std::map<const char *, Param> paramList;

    but if the param is a float array i carry in the Param object useless
    data like sdefault & idefault. Therefore Param is "heavier" than it
    should. I am not sure this is very elegant (although simple).

    I thought of having some sort of Data class that would hold a void*
    variable pointer to an array of data. But of course using std::vector
    is better since having a void * data type of situation makes have to
    deal with allocating/deallocating memory.

    class Data
    {
    public:
    void *data;
    Data( ParamType type, void *d, unsigned n )
    {
    switch( type )
    case kFloat: data = new float[n];
    memcpy(data,d,sizoef(float)*n); break;
    case kInt: data = new int[n]; memcpy(data, d, sizeof(int)*n);
    break;
    case kString: /* etc */
    }
    ~Data() { /* release mem */ }
    };

    Could anybody advise me of the best way of doing this please (in terms
    of code robustness, simplicity of use, better c++ coding, memory &
    speed efficiency, etc).

    Thanks a lot -mark
    , Mar 29, 2007
    #1
    1. Advertising

  2. On 29 Mar, 12:39, "" <> wrote:
    > Hi everyone
    >
    > I need to come up with an efficient solution to add/remove/access
    > parameters to an object. Lets say I create an object "Cart" and at run
    > time based on the user input, lets say we add to this "Cart" object 3
    > Oranges 4 Apples and 1 Salad (stupid example I know). Whenever we do
    > something with this cast object we want to be able to have access to
    > all the data that it holds (3 oranges, 4 apples, 1 salad).
    >
    > in pseudo code it would do something like that
    >
    > Cart *cart = new Cart;
    > Orange orange[4] = { orange1, orange2, orange3, orange4 };
    > Cart.SetParameter( "SomeOrange", orange ); // copy the 4 orange in
    > memory
    > Orange *iterOrange = Cart.GetParameter( "SomeOrange" );
    > for ( unsigned i = 0; i < 4; ++i )
    > Orange *o = iterOrange;
    >
    > To get something like that to work the Cart class would have a member
    > variable that would look like that.
    >
    > std::map<const char *, Data> dict;
    >
    > So a unique name is associated with each data, such that we can look
    > for that parameter name later on when we call GetParameter.
    >
    > I looked a little bit on the net and found a few documents on C++
    > patterns that seem to do what I need. They seem to be called Parameter
    > List, Parameter Block or Anything Patterns. But I have a hard time
    > making to work or find a good implementation example. It sounds like
    > some API are using these patterns. I have heard of the 3DMaya API &
    > the nVidia Gelato API. It is used for these 3D renderers because it
    > allows to add any data of any type at run time for example to lets say
    > geometric primitives (and I want to use it for that purpose).
    >
    > I am not sure what is the best way of doing that so was wondering if
    > someone knows a good implementation of these patterns or could put me
    > on the right track to write my own. I thought of simply doing
    > something like that :
    >
    > enum ParamType { kFloat, kInt, kString };
    >
    > class Param
    > {
    > public:
    > ParamType type;
    > std::vector<float> fdefault;
    > std::vector<const char *> sdefault;
    > std::vector<int> idefault;
    > Param() {}
    >
    > };
    >
    > std::map<const char *, Param> paramList;
    >
    > but if the param is a float array i carry in the Param object useless
    > data like sdefault & idefault. Therefore Param is "heavier" than it
    > should. I am not sure this is very elegant (although simple).
    >
    > I thought of having some sort of Data class that would hold a void*
    > variable pointer to an array of data. But of course using std::vector
    > is better since having a void * data type of situation makes have to
    > deal with allocating/deallocating memory.
    >
    > class Data
    > {
    > public:
    > void *data;
    > Data( ParamType type, void *d, unsigned n )
    > {
    > switch( type )
    > case kFloat: data = new float[n];
    > memcpy(data,d,sizoef(float)*n); break;
    > case kInt: data = new int[n]; memcpy(data, d, sizeof(int)*n);
    > break;
    > case kString: /* etc */
    > }
    > ~Data() { /* release mem */ }
    >
    > };
    >
    > Could anybody advise me of the best way of doing this please (in terms
    > of code robustness, simplicity of use, better c++ coding, memory &
    > speed efficiency, etc).


    If you have a limited set of items that can be placed in the Cart and
    if they all have some operations in common it would probably be
    easiest to simply let them inherit from some base-type. Failing that
    you need a heterogeneous container, it's covered slightly in the FAQ:
    http://www.parashift.com/c -faq-lite/containers.html#faq-34.4 and you
    can find some implementations by googling, Boost.Any is one such
    container: http://www.boost.org/doc/html/any.html

    --
    Erik Wikström
    =?iso-8859-1?q?Erik_Wikstr=F6m?=, Mar 29, 2007
    #2
    1. Advertising

  3. Guest

    On Mar 29, 11:19 pm, "Erik Wikström" <>
    wrote:
    > On 29 Mar, 12:39, "" <> wrote:
    >
    >
    >
    > > Hi everyone

    >
    > > I need to come up with an efficient solution to add/remove/access
    > > parameters to an object. Lets say I create an object "Cart" and at run
    > > time based on the user input, lets say we add to this "Cart" object 3
    > > Oranges 4 Apples and 1 Salad (stupid example I know). Whenever we do
    > > something with this cast object we want to be able to have access to
    > > all the data that it holds (3 oranges, 4 apples, 1 salad).

    >
    > > in pseudo code it would do something like that

    >
    > > Cart *cart = new Cart;
    > > Orange orange[4] = { orange1, orange2, orange3, orange4 };
    > > Cart.SetParameter( "SomeOrange", orange ); // copy the 4 orange in
    > > memory
    > > Orange *iterOrange = Cart.GetParameter( "SomeOrange" );
    > > for ( unsigned i = 0; i < 4; ++i )
    > > Orange *o = iterOrange;

    >
    > > To get something like that to work the Cart class would have a member
    > > variable that would look like that.

    >
    > > std::map<const char *, Data> dict;

    >
    > > So a unique name is associated with each data, such that we can look
    > > for that parameter name later on when we call GetParameter.

    >
    > > I looked a little bit on the net and found a few documents on C++
    > > patterns that seem to do what I need. They seem to be called Parameter
    > > List, Parameter Block or Anything Patterns. But I have a hard time
    > > making to work or find a good implementation example. It sounds like
    > > some API are using these patterns. I have heard of the 3DMaya API &
    > > the nVidia Gelato API. It is used for these 3D renderers because it
    > > allows to add any data of any type at run time for example to lets say
    > > geometric primitives (and I want to use it for that purpose).

    >
    > > I am not sure what is the best way of doing that so was wondering if
    > > someone knows a good implementation of these patterns or could put me
    > > on the right track to write my own. I thought of simply doing
    > > something like that :

    >
    > > enum ParamType { kFloat, kInt, kString };

    >
    > > class Param
    > > {
    > > public:
    > > ParamType type;
    > > std::vector<float> fdefault;
    > > std::vector<const char *> sdefault;
    > > std::vector<int> idefault;
    > > Param() {}

    >
    > > };

    >
    > > std::map<const char *, Param> paramList;

    >
    > > but if the param is a float array i carry in the Param object useless
    > > data like sdefault & idefault. Therefore Param is "heavier" than it
    > > should. I am not sure this is very elegant (although simple).

    >
    > > I thought of having some sort of Data class that would hold a void*
    > > variable pointer to an array of data. But of course using std::vector
    > > is better since having a void * data type of situation makes have to
    > > deal with allocating/deallocating memory.

    >
    > > class Data
    > > {
    > > public:
    > > void *data;
    > > Data( ParamType type, void *d, unsigned n )
    > > {
    > > switch( type )
    > > case kFloat: data = new float[n];
    > > memcpy(data,d,sizoef(float)*n); break;
    > > case kInt: data = new int[n]; memcpy(data, d, sizeof(int)*n);
    > > break;
    > > case kString: /* etc */
    > > }
    > > ~Data() { /* release mem */ }

    >
    > > };

    >
    > > Could anybody advise me of the best way of doing this please (in terms
    > > of code robustness, simplicity of use, better c++ coding, memory &
    > > speed efficiency, etc).

    >
    > If you have a limited set of items that can be placed in the Cart and
    > if they all have some operations in common it would probably be
    > easiest to simply let them inherit from some base-type.


    Thanks Erik for your answer. They do have comment operations but are
    quite different still I think. For example float, integers, Points,
    Vectors, Normals, Matrices, etc are all numbers and so all have
    arithmetic opertations (+ - / ... )
    I think in the code I develop at the moment I do have 3 basic types,
    int, float & string.
    , Mar 29, 2007
    #3
  4. Guest

    Boost.Any is one such
    > container:http://www.boost.org/doc/html/any.html


    I just looked at boost::any and it looks like what I need. Is there
    any restrictions as to why it might not be a good idea to use it ?
    Otherwise it sounds like the way to go isn't it ?
    , Mar 29, 2007
    #4
  5. Matteo Guest

    On Mar 29, 2:19 pm, "" <> wrote:
    > Boost.Any is one such
    >
    > > container:http://www.boost.org/doc/html/any.html

    >
    > I just looked at boost::any and it looks like what I need. Is there
    > any restrictions as to why it might not be a good idea to use it ?
    > Otherwise it sounds like the way to go isn't it ?


    If you have a known set of types (i.e. just
    int,float,string,vector,matrix,etc), you may wish to use
    boost::variant instead of boost::any. Boost::variant does not perform
    any memory allocation (which boost::any must do behind the scenes) and
    thus has less overhead. It also has a nice visitor interface which
    lets you actually operate on the data without having to check its
    type.

    However, if you're writing a library, and you just want users to be
    able to add and remove any type of data, then boost::any is the way to
    go.

    Be warned - both any and variant can produce a disheartening amount of
    compiler error output if you make a mistake.
    -matt
    Matteo, Mar 29, 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. Showjumper
    Replies:
    1
    Views:
    690
    Showjumper
    Mar 19, 2005
  2. crichmon
    Replies:
    4
    Views:
    469
    Mabden
    Jul 7, 2004
  3. morrell
    Replies:
    1
    Views:
    933
    roy axenov
    Oct 10, 2006
  4. Lee Griffiths
    Replies:
    8
    Views:
    128
    Roger Pack
    Feb 13, 2011
  5. Udaykumar Kunapuli

    grepping a list of patterns in a larger list

    Udaykumar Kunapuli, May 6, 2014, in forum: Perl Misc
    Replies:
    13
    Views:
    107
    Dr.Ruud
    May 13, 2014
Loading...

Share This Page