title: C++ - How to specialise a custom type for std::max without overloading comparison operators?
body: <p>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 <code>float</code>. The data type I'm writing is a wrapper for a vector (eventually a SIMD vector of four floats, not a <code>std::vector</code>) and I want to provide a <code>max</code> function to compare two vectors and return a new vector that is the maximum of each element. This is different to <code>std::max</code> which uses the comparison operator but the concept is the same.</p>
  
  <p>The problem is that I have a generic function called <code>do_max(T x, T y)</code> that applies <code>max</code> to the inputs. I need this function to work for both scalar float inputs (e.g. <code>do_max&lt;float&gt;(0.1f, 0.2f)</code>) <strong>and</strong> my vector class (e.g. <code>do_max&lt;MyVector&gt;(v0, v1)</code>).</p>
  
  <p>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.</p>
  
  <p>The code I have below does not compile unless you comment out the <code>float f0 = ...</code> line:</p>
  
  <pre><code>// compile with: g++ -std=c++11 max.cc -o max
  #include &lt;algorithm&gt;
  #include &lt;vector&gt;
  
  class MyVector {
  public:
    MyVector(float x0, float x1, float x2, float x3) : storage_ { x0, x1, x2, x3 } {};
  
    friend MyVector max(MyVector lhs, const MyVector &amp; rhs);
  
  private:
    std::vector&lt;float&gt; storage_;
  };
  
  MyVector max(MyVector lhs, const MyVector &amp; rhs) {
    for (size_t i = 0; i &lt; lhs.storage_.size(); ++i) {
      lhs.storage_[i] = std::max(lhs.storage_[i], rhs.storage_[i]);
    }
    return lhs;
  }
  
  template&lt;typename T&gt;
  T do_max(const T &amp; x, const T &amp; 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;
  }
  </code></pre>
  
  <p>I have a feeling I need a way to make that <code>max</code> function resolve to <code>std::max</code> for scalar types, and my specialised <code>max</code> friend function for the MyVector type.</p>
  
  <p>How to I define a max function that works in this way? Is it better to forget about <code>std::max</code> and use my own max function that is specialised for <code>MyVector</code> and also provides implementation for scalar types like <code>float</code>?</p>
  
  <p>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 <code>max</code> will be used with other functions like <code>min</code>, <code>exp</code>, <code>pow</code> as well.</p>