Jmin, et. al. need some over-engineering


#1

Oh you didn’t think jmin() could be improved? Let me show you!

This is how jmin looks now

template <typename Type> inline Type jmin (const Type a, const Type b) { return (b < a) ? b : a; }

I would love it if a and b could be different types:

template <typename TypeA, typename TypeB> inline TypeA jmin (const TypeA a, const TypeB b) { return (b < a) ? TypeA(b) : a; }

Why? Well consider this use-case:

        int numSamples;
        int64 streamPos;
        //...
        if (streamPos < 0)
        {
          const int amountToZero = jmin (numSamples, 0 - streamPos);
          //...
        }

Right now this generates a compile error. But it should be legit because we’re doing a min and not any actual arithmetic. If streamPos is less than -2^32 the comparison and assignment is still valid.

Ideally there would be a static_assert about the std::numeric_limits::max_value being less than std::numeric_limits::max_value in order that the return value fit into a TypeA.

Or something…

Jules could something like this work?


#2

hmmmm… my “edge case” warning light is flashing. I suspect there are a lot of subtle ways in which it could blow up.

The thing that immediately bothers me about it is that it’s not symmetrical - if you pass in two different types, it’s unclear what the return type will be. So for example, if you gave it a double and a float, the accuracy of the result would depend on the order in which you pass them, and that’s messy.

Nah… Much safer just to make it the responsibility of the caller to ensure that they’re passing in two objects of the same type!


#3

fully agreed.

what on earth is so wrong with just casting/rounding/etc. to logically compare matching types?


#4

+1


#5

[quote=“haydxn”]fully agreed.

what on earth is so wrong with just casting/rounding/etc. to logically compare matching types?[/quote]

When you are mixing a lot of 32-bit and 64-bit integers and doing sample offest / count calculations, it gets very messy, very quickly.


#6

Maybe, but if jmin is messy, then it’s clearly not the right tool for the job. If you find yourself repeatedly having to cast things, you should probably write yourself a little task-specific helper function instead, which takes the correct types, and does the right thing with them. That’d be more readable, and probably less error-prone too.


#7

Thats actually a great idea, and it should help get rid of tons of warnings about the loss of data due to different size integers that I had to band-aid over by disabling those warnings.

Although my sample offsets are all int64, any variable that manages a count of samples uses int. For example in juce::AudioSampleBuffer, and also when I create bins of samples (i.e. for FFT) I am doing

int64 startingSample;
int samplesPerBlock;
// ...
int arrayIndex = startingSample / samplesPerBlock;

just one of many examples where int and int64 are mixed together…and I certainly don’t expect juce::Array() to take int64 for index or size arguments.