meowsqueak meowsqueak - 1 year ago 59
C++ Question

C++ - How to specialise a custom type for std::max without overloading comparison operators?

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

. The data type I'm writing is a wrapper for a vector (eventually a SIMD vector of four floats, not a
) and I want to provide a
function to compare two vectors and return a new vector that is the maximum of each element. This is different to
which uses the comparison operator but the concept is the same.

The problem is that I have a generic function called
do_max(T x, T y)
that applies
to the inputs. I need this function to work for both scalar float inputs (e.g.
do_max<float>(0.1f, 0.2f)
) and my vector class (e.g.
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 -o max
#include <algorithm>
#include <vector>

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

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

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
function resolve to
for scalar types, and my specialised
friend function for the MyVector type.

How to I define a max function that works in this way? Is it better to forget about
and use my own max function that is specialised for
and also provides implementation for scalar types like

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
will be used with other functions like
as well.

Answer Source

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>.