Re: Characterize parameters by type
* Rune Allnor:
On 1 Jul, 10:55, "Alf P. Steinbach" <al...@start.no> wrote:
* Rune Allnor:
On 30 Jun, 20:37, "Alf P. Steinbach" <al...@start.no> wrote:
What you need is a branch to code that expects only the relevant of the C++
types, and you can't do that automagically by a normal 'return'. If you don't
care about nano-sec performance the simplest solution is to use an exception.
Yes, I know very well that that is *heretical*, since most compilers optimize
for exceptions denoting failure and since C and C++ programmers are obsessively
concerned with nano-sec performance, but this is one of the exceptional cases.
...
I must admit I thought about the base-class / derived-class
hierarchy just after I posted the first post yesterday,
before the first reply appeared.
Hm, I think you're referring to mzdude's reply, about using a polymorphic
function result.
Yep.
That defeats the goal of static type checking, so it's just ungood.
With the caveat that I don't have the grasp of C++' tech
lingo, *one* plymorphic result is what I want to return
from this argument check routine.
Yes, that's clear now from the more detailed description below.
As more is revealed of the problem, the solution space shrinks.
And what I thought was the problem, was not. :-)
As for 'ungood', it's not a solution I would have chosen
anywhere else, but I'm constrained by how matlab is already
doing things.
Also keep in mind that I tend, as far as possible, to use
argument type matches, as opposed to switch-case constructs,
to discriminate between options whereever I can. This
'idee fixee' of mine pretty much dominates how I design
my programs.
Happily we're on the same wavelength here. The case against switch (heh) was
pretty forcefully expressed by Bertrand Meyer in his classic Eiffel book "Object
Oriented Software Construction". It is by extension also a case against
enumeration types, and Betrand thought it was so much that that he didn't
support enumeration types in Eiffel: more ungood than good, he thought...
Now, due to the constraints of the context of this particular
program, I can not avoid them completely (I do need to
perform such a test on the argument recieved from matlab),
but once it is done, I prefer to use polymorphism based
on types, everywhere else.
However, given your new more clear description of the problem (else-thread),
that foo() is called with MatLab args, that is, that those args do not stem from
a call *to* MatLab, packaging the type discrimination as a general routine only
makes sense if you have several different routines that are called by MatLab,
all with the same convention for dynamic type specification.
Is that the case?
Yes. Specifically, I have a number of routines for designing
digital filters. The C++ design routines take a filter
specification object as argument, and based on the type
of this argument the proper computations are done:
class GenericFilterSpec{};
class LowPassSpec : public GenericFilterSpec{};
class HighPassSpec : public GenericFilterSpec{};
class BandPassSpec : public GenericFilterSpec{};
class BandStopSpec : public GenericFilterSpec{};
So in the interface routine the user calls from matlab,
I need a way to transform the input arguments, that
describe the desired response, to the classes the
business routines require as arguments.
OK.
With the original problem description it seemed the problem was:
CASE A:
* foo() calls MatLab.
* the MatLab result is data that is to be treated as 1 of 4
unrelated types.
* this also happens for other routines than foo().
My current, twice updated understanding of the problem is
CASE B:
* foo() is called by MatLab.
* MatLab supplies argument data that is to be treated as 1 of 4
similar types, which can be treated polymorphically, that is
without knowledge of the actual type.
* this also happens for other routines than foo().
The scenario really does matter.
If not, then just do the discrimination directly in the single routine called by
MatLab. Or perhaps factor the logic out as a routine returning an enum, then do
a switch. The *simplest* is often the best. ;-)
Well, yes, maybe. Maybe the size of this particular problem
(just four options) is too small to warrant an involved
solution, but I want to get a grasp of the ideas.
And agian: I just don't want to use switches and enums
if I can in any way avoid it. At some time this C++ filter
design class might be expanded by more awkward stuff.
There are no reasons to expect that such expansions would
fit nicely into the enum frame.
Your suggestion is just insane enough to be appealing.
Yeah. In the land of the blind, the one-eyed man has a very troubled life. ;-)
We may laugh at Monty Python's flotation test for whiches (floats => which, so
burn her/him, drowns => uh oh, not a which), but since we're both Norwegians: as
far as I know that test was invented in and only practiced in Norway...
Ah. All of a sudden a lot of stuff made a lot more sense...
Yeah. :-)
Of course I meant to write "witch".
Actually, I'm a bit more hesitant today than I was yesterday.
Getting back to your code:
try
{
foo();
assert( "Should never get here" && 0 );
}
catch( Case1Class const& r )
{
// Deal with Case1Class
}
catch( Case2Class const& r )
{
// Deal with Case2Class
}
Now, you might have removed switch-case *syntax*, but you
haven't removed the undesireable switch-case *construct*:
- There is a test for the argument
- There is a list of individual steps
that match each possible outcome of the test.
For case A the exception trick provides strong static type checking, no
possibility of accessing the data using the wrong type: *type safe*.
So for case A it's far more than syntax: the different syntax is there just a
necessity for expressing the functionality.
For case B the code it's embedded in presumably has access to the MathLab data,
so for that case it's indeed just syntax, and an unconventional at that.
As I said above, I just don't like this kind of stuff,
so I don't want to use it if I have half a choise.
Of course, one could set up a class hierarchy for the
exceptions, similar to the filter specs above, and use,
say, a visitor pattern to get the correct routines called.
Huh?
I mentioned the callback interface as an *alternative* to exceptions, i.e., not
involving any exception trick.
Anyway, I assume we're now into case B, not my original assumption of case A,
and that matters.
But if you do, you are back to mzdude's solution, only
this time it is obfuscated by being wrapped inside the
exception mechanism, which makes for a highly unusual
control loop construct.
Nah, I think mzdude's polymorphic return is the one
I'll be investigating further.
Yes, that's the solution that it seems makes most sense for case B.
The exception thing, however, was a nice, if unconventional, idea for case A,
wasn't it? ;-)
Cheers & hth.,
- Alf
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]