Suitable data structure for a "context sensitive" 3-tuple?

S

Susan Baker

Hi,

I want to store data in a 3-tuple {a,b,c}.
Element a is an enumeration, and element c is an enumeration which is
specific (i.e. determined) by a.

An example will help clarify further. I give two examples, one of a
valid instance, and the other, an invalid instance.

typedef enum { bovine, gamebird, seafood } general_meat ;

Note: each of the elements above is a category of its own. I can
further partition the seafood category to yield the following grouping:

typedef enum { scallops, lobster, cod, prawn, salmon} seafood ;


class Meal {
general_meat m ;
bool cook_first ;
X data_type_that_will_accept_specific_types_of_general_meat_m ;
}

I hope the illustration above provides some illumination on the problem.
class Meal will (obviously?) have to be a template class - but I
don't know how to enforce X to be a subset (i.e. a permissable type)
determined by m.

I look forward to any ideas for a possible solution. Thanks
 
S

Susan Baker

Susan said:
Hi,

I want to store data in a 3-tuple {a,b,c}.
Element a is an enumeration, and element c is an enumeration which is
specific (i.e. determined) by a.

An example will help clarify further. I give two examples, one of a
valid instance, and the other, an invalid instance.

typedef enum { bovine, gamebird, seafood } general_meat ;

Note: each of the elements above is a category of its own. I can further
partition the seafood category to yield the following grouping:

typedef enum { scallops, lobster, cod, prawn, salmon} seafood ;


class Meal {
general_meat m ;
bool cook_first ;
X data_type_that_will_accept_specific_types_of_general_meat_m ;
}

I hope the illustration above provides some illumination on the problem.
class Meal will (obviously?) have to be a template class - but I don't
know how to enforce X to be a subset (i.e. a permissable type)
determined by m.

I look forward to any ideas for a possible solution. Thanks

Ok. Here are the two examples (of objects) I promised earlier:

meal1 { seafood, no, scallops } // <- valid
meal2 { bovine, yes, scallops } //<- invalid
 
D

Dan Cernat

Susan said:
Hi,

I want to store data in a 3-tuple {a,b,c}.
Element a is an enumeration, and element c is an enumeration which is
specific (i.e. determined) by a.

An example will help clarify further. I give two examples, one of a
valid instance, and the other, an invalid instance.

typedef enum { bovine, gamebird, seafood } general_meat ;

Note: each of the elements above is a category of its own. I can
further partition the seafood category to yield the following grouping:

typedef enum { scallops, lobster, cod, prawn, salmon} seafood ;


class Meal {
general_meat m ;
bool cook_first ;
X data_type_that_will_accept_specific_types_of_general_meat_m ;
}

I hope the illustration above provides some illumination on the problem.
class Meal will (obviously?) have to be a template class - but I
don't know how to enforce X to be a subset (i.e. a permissable type)
determined by m.

I look forward to any ideas for a possible solution. Thanks

What is wrong with inheritance? Make
data_type_that_will_accept_specific_types_of_general_meat_m a pointer
to a general_meal. Derive bovine, gamberid and seafood from
general_meal.

dan
 
S

Susan Baker

Dan said:
What is wrong with inheritance? Make
data_type_that_will_accept_specific_types_of_general_meat_m a pointer
to a general_meal. Derive bovine, gamberid and seafood from
general_meal.

dan

Is general_meal a new class, or did you mean general_meat ?. I can see
where you're going with the inheritence suggestion. I could have a
heirarchy like:

meat
|
-------------------------
| | |
bovine gamebird seafood


and then sub-class each one of them accordingly. This is one way of ding
it - it also means a lot of coding - with all its attendant problems. I
was wondering if there was a way of applying generic programming
philosophy so I could have one generic factory that produces each of
these groupings (bovine, gamebird etc).

When using any of these meat derived classes (which should really be
abstract - since they are classifications), the derived class can only
instantiate with meaningful values, so that if I ask for a seafood Meal,
I do not end up with raw pork (for instance0. since pork is not a valid
member (enumeration item if you like) for the class seafood. I know all
of this can be done using inheritance and judious inspection of types
being passed in the class constructor etc - but this is not easily
extendable, for example, if I decide to allow new items to be part of
the seafood category, I have an awful lot of refactoring to do - I was
just wondering if there was a way of writing this in a generic way (if
not all, then at least some of it).
 
D

Dan Cernat

Susan,

I took a look at your second post

meal1 { seafood, no, scallops } // <- valid
meal2 { bovine, yes, scallops } //<- invalid

why would you want to do this? Pass in the scallops and that is all. No
need for validation. This is using inheritance. So, before talking
more, what is the exact problem you are trying to solve? So far you are
asking help in implementing _a_ solution, but what is your problem?
There may be better ways to solve it.

dan
 
S

Susan Baker

Dan said:
Susan,

I took a look at your second post

meal1 { seafood, no, scallops } // <- valid
meal2 { bovine, yes, scallops } //<- invalid

why would you want to do this? Pass in the scallops and that is all. No
need for validation. This is using inheritance. So, before talking
more, what is the exact problem you are trying to solve? So far you are
asking help in implementing _a_ solution, but what is your problem?
There may be better ways to solve it.

dan

Hi Dan,

Just FYI, the examples I gave was not pseudocode (i.e. I was not passing
anything to the meal types). basically, what I meanto say was that a
valid meal (meal1), could comprise of the following "properties :

{
seafood /*food category*/,
no /*no cooking reqd b4 consumption*/,
scallops /* the specific food type */
}

In the second example I gave, the object was invalid because scallops do
not belong to the bovine food category. The actual problem statement is
too domain specific (i.e. requires too much speciliazed domain
knowledge) to go into detail here - it will simply further obfuscucate
the problem, besides, my boss is not likely to be too pleased with me
discussing this here (we've signed an NDA etc ...). However, the
description I gave is accurate. The more I think about it, the more I am
convinced to keep things simple. I think the inheritance route is the
way forward - once I've got that working, I'll look to "generalize" the
code later.

Thanks for your help anyhows..
 
D

Dan Cernat

Susan said:
Hi Dan,

Just FYI, the examples I gave was not pseudocode (i.e. I was not passing
anything to the meal types). basically, what I meanto say was that a
valid meal (meal1), could comprise of the following "properties :

{
seafood /*food category*/,
no /*no cooking reqd b4 consumption*/,
scallops /* the specific food type */
}

In the second example I gave, the object was invalid because scallops do
not belong to the bovine food category.
[snip]

Hi Susan,

scallops could be only seafood. There is no need to have the food
category in the meal. This way, the meals are always valid:
class meal
{
private:
bool cooked;
Food* food; /* the specific food type */
public:
meal(bool Cooked, Food* SpecificFood)
{
cooked = Cooked;
food = SpecificFood;
}

FoodCateg GetFoodCategory()
{
food->GetCategory();
}
};


meal m1(false, new Scallops);
meal m2(true, new GroundMeat);

How you store the category inside the Food class is a different story.
It could be a member variable or an inheritance chain or a templated
class. your call.

dan
 
J

John Carson

Susan Baker said:
Hi,

I want to store data in a 3-tuple {a,b,c}.
Element a is an enumeration, and element c is an enumeration which is
specific (i.e. determined) by a.

An example will help clarify further. I give two examples, one of a
valid instance, and the other, an invalid instance.

typedef enum { bovine, gamebird, seafood } general_meat ;

Note: each of the elements above is a category of its own. I can
further partition the seafood category to yield the following
grouping:
typedef enum { scallops, lobster, cod, prawn, salmon} seafood ;


class Meal {
general_meat m ;
bool cook_first ;
X data_type_that_will_accept_specific_types_of_general_meat_m ;
}

I hope the illustration above provides some illumination on the
problem. class Meal will (obviously?) have to be a template class -
but I don't know how to enforce X to be a subset (i.e. a permissable type)
determined by m.

I look forward to any ideas for a possible solution. Thanks

There may be more elegant ways to do it, but this seems to work:

enum general_meat { bovine, gamebird, seafood };

enum bovine_subtype { rump, sirloin, topside};
enum gamebird_subtype { pheasant, duck };
enum seafood_subtype { scallops, lobster, cod, prawn, salmon};

// general template class
template <general_meat gm>
struct SubTypeEnum
{};

// specialisations for each general_meat case

template<>
struct SubTypeEnum<bovine>
{
typedef bovine_subtype subtype;
};

template<>
struct SubTypeEnum<seafood>
{
typedef seafood_subtype subtype;
};

template<>
struct SubTypeEnum<gamebird>
{
typedef gamebird_subtype subtype;
};



template<general_meat gm>
class Meal : private SubTypeEnum<gm>
{
using typename SubTypeEnum<gm>::subtype;
bool cook_first ;
subtype s;
public:
Meal(bool cf, subtype st) : cook_first(cf), s(st)
{}
};



int main()
{
Meal<seafood> m1(true, scallops); // compiles

Meal<seafood> m2(true, rump); // won't compile
}

To add a new subtype, you just have to add it to the enum for that subtype.

To add a new type (say, pork), you need to:

1. Add pork to the general_meat enum.
2. Define a enum pork_subtype.
3. Add

template<>
struct SubTypeEnum<pork>
{
typedef pork_subtype subtype;
};
 
J

John Carson

John Carson said:
template<general_meat gm>
class Meal : private SubTypeEnum<gm>
{
using typename SubTypeEnum<gm>::subtype;
bool cook_first ;
subtype s;
public:
Meal(bool cf, subtype st) : cook_first(cf), s(st)
{}
};


I omitted the template parameter from the list of variables since I made no
use of it, but you probably want to add it back in:


template<general_meat gm>
class Meal : private SubTypeEnum<gm>
{
using typename SubTypeEnum<gm>::subtype;
general_meat meat_type;
bool cook_first ;
subtype s;
public:
Meal(bool cf, subtype st) : meat_type(gm), cook_first(cf), s(st)
{}
};
 
S

Susan Baker

John said:
There may be more elegant ways to do it, but this seems to work:

enum general_meat { bovine, gamebird, seafood };

enum bovine_subtype { rump, sirloin, topside};
enum gamebird_subtype { pheasant, duck };
enum seafood_subtype { scallops, lobster, cod, prawn, salmon};

// general template class
template <general_meat gm>
struct SubTypeEnum
{};

// specialisations for each general_meat case

template<>
struct SubTypeEnum<bovine>
{
typedef bovine_subtype subtype;
};

template<>
struct SubTypeEnum<seafood>
{
typedef seafood_subtype subtype;
};

template<>
struct SubTypeEnum<gamebird>
{
typedef gamebird_subtype subtype;
};



template<general_meat gm>
class Meal : private SubTypeEnum<gm>
{
using typename SubTypeEnum<gm>::subtype;
bool cook_first ;
subtype s;
public:
Meal(bool cf, subtype st) : cook_first(cf), s(st)
{}
};



int main()
{
Meal<seafood> m1(true, scallops); // compiles

Meal<seafood> m2(true, rump); // won't compile
}

To add a new subtype, you just have to add it to the enum for that subtype.

To add a new type (say, pork), you need to:

1. Add pork to the general_meat enum.
2. Define a enum pork_subtype.
3. Add

template<>
struct SubTypeEnum<pork>
{
typedef pork_subtype subtype;
};
This is the approach I'm looking for. Thanks very much - lots of "food
for thought" (pun intended !). Thanks
 
K

Karl Heinz Buchegger

Susan said:
Just FYI, the examples I gave was not pseudocode (i.e. I was not passing
anything to the meal types). basically, what I meanto say was that a
valid meal (meal1), could comprise of the following "properties :

{
seafood /*food category*/,
no /*no cooking reqd b4 consumption*/,
scallops /* the specific food type */
}

Why should a meal know to which category a specific food type belongs.
If it really needs to know, it can always ask the food type for this
information.
 
S

Susan Baker

Karl said:
Why should a meal know to which category a specific food type belongs.
If it really needs to know, it can always ask the food type for this
information.

I can see your point. However, what I want to do is to create an
infrastructure that allows me to create valid object types, with minimal
room for error - I suppose a lot of this can be done using an abstract
factory design pattern - but I prefer the generic programming approach
using templates (if this is possible). Although the problem
representation may seem flawed from your point of view - I can assure
you that it is valid with the benefit of specific domain knowledge.
Valid objects need to be created so that they can be de-composed at a
later stage - an invalid object will lead to an equally invalid
decomposed object (or set of objects as the case may be).
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top