meowsqueak - 6 months ago 23

C++ Question

I'm looking for advice on how to implement a specialised "max" (i.e. maximum) function for a custom data type that also works with scalar types like

`float`

`std::vector`

`max`

`std::max`

The problem is that I have a generic function called

`do_max(T x, T y)`

`max`

`do_max<float>(0.1f, 0.2f)`

`do_max<MyVector>(v0, v1)`

Note that overloading MyVector's comparison operators is not an option because I'm using those with the SIMD intrinsics that are quite different: they create an integer vector containing 1, 0, -1 for each element comparison rather than returning a boolean result.

The code I have below does not compile unless you comment out the

`float f0 = ...`

`// compile with: g++ -std=c++11 max.cc -o max`

#include <algorithm>

#include <vector>

class MyVector {

public:

MyVector(float x0, float x1, float x2, float x3) : storage_ { x0, x1, x2, x3 } {};

friend MyVector max(MyVector lhs, const MyVector & rhs);

private:

std::vector<float> storage_;

};

MyVector max(MyVector lhs, const MyVector & rhs) {

for (size_t i = 0; i < lhs.storage_.size(); ++i) {

lhs.storage_[i] = std::max(lhs.storage_[i], rhs.storage_[i]);

}

return lhs;

}

template<typename T>

T do_max(const T & x, const T & y) {

// if this is std::max then it won't compile for MyVector

return max(x, y);

}

int main(int argc, char * argv[]) {

MyVector v0 { 0.1, 0.2, 0.3, 0.4 };

MyVector v1 { 0.4, 0.3, 0.2, 0.1 };

MyVector v2 = do_max(v0, v1);

// Comment out the following line to successfully compile.

// However I'd like this to work for scalar types too:

float f0 = do_max(0.1f, 0.2f);

return 0;

}

I have a feeling I need a way to make that

`max`

`std::max`

`max`

How to I define a max function that works in this way? Is it better to forget about

`std::max`

`MyVector`

`float`

The background for this is that I'm implementing a data path that I hope will work with both MyVector and scalar types (as a parameterised type at compile time). I already have arithmetic working, however the solution for

`max`

`min`

`exp`

`pow`

Answer

Classic solution:

```
template<typename T>
T do_max(const T & x, const T & y) {
using std::max;
return max(x, y);
}
```

Argument-Dependent Lookup finds your `max`

, for `float`

this does not happen and you get `std::max<float>`

.