title: Can I use something like enable_if with an implicit conversion operator?
body: <p>I have a (basically completed) matrix class (later in this post). If the matrix is a 1x1 matrix, then I'd like to have an implicit conversion to the backing type (e.g. a 1x1 float matrix should convert to a float).</p>
  
  <p>Is there a way to do that without creating a specialization and duplicating all the methods inside Matrix? (e.g. using something like <code>std::enable_if</code>?) I basically want to enable the implicit conversion if and only if ROWS == COLS == 1.</p>
  
  <pre><code>template &lt;std::size_t ROWS, std::size_t COLS = 1, typename BackingType = float&gt;
  class Matrix
  {
      BackingType data[ROWS][COLS];
  public:
      Matrix()
      {
          for(std::size_t rdx = 0; rdx &lt; ROWS; ++rdx)
          {
              for (std::size_t cdx = 0; cdx &lt; COLS; ++cdx)
              {
                  data[rdx][cdx] = 0;
              }
          }
      }
      const BackingType&amp; Member(std::size_t index) const
      {
          assert(index &lt; ROWS*COLS);
          return *(static_cast&lt;BackingType*&gt;(&amp;data[0][0]) + index);
      }
      BackingType&amp; Member(std::size_t index)
      {
          assert(index &lt; ROWS*COLS);
          return *(static_cast&lt;BackingType*&gt;(&amp;data[0][0]) + index);
      }
      const BackingType&amp; Member(std::size_t rowIndex, std::size_t colIndex) const
      {
          assert(rowIndex &lt; ROWS);
          assert(colIndex &lt; COLS);
          return data[rowIndex][colIndex];
      }
      BackingType&amp; Member(std::size_t rowIndex, std::size_t colIndex)
      {
          assert(rowIndex &lt; ROWS);
          assert(colIndex &lt; COLS);
          return data[rowIndex][colIndex];
      }
      Matrix&lt;COLS, ROWS, BackingType&gt; Transpose() const
      {
          Matrix&lt;COLS, ROWS, BackingType&gt; result;
          for(std::size_t rowIdx = 0; rowIdx &lt; ROWS; rowIdx++)
          {
              for (std::size_t colIdx = 0; colIdx &lt; COLS; ++colIdx)
              {
                  result.Member(colIdx, rowIdx) = Member(rowIdx, colIdx);
              }
          }
          return result;
      }
      template &lt;std::size_t otherRows, std::size_t otherCols&gt;
      Matrix&lt;ROWS + otherRows, COLS, BackingType&gt; AugmentBelow(const Matrix&lt;otherRows, otherCols, BackingType&gt;&amp; other)
      {
          static_assert(COLS == otherCols, "Columns must match for a vertical augmentation.");
          Matrix&lt;ROWS + otherRows, COLS, BackingType&gt; result;
          for (std::size_t curRow = 0; curRow &lt; ROWS; ++curRow)
          {
              for (std::size_t curCol = 0; curCol &lt; COLS; ++curCol)
              {
                  result.Member(curRow, curCol) = Member(curRow, curCol);
              }
          }
          for (std::size_t curRow = ROWS; curRow &lt; (ROWS + otherRows); ++curRow)
          {
              for (std::size_t curCol = 0; curCol &lt; COLS; ++curCol)
              {
                  result.Member(curRow, curCol) = other.Member(curRow - ROWS, curCol);
              }
          }
          return result;
      }
      template &lt;std::size_t otherRows, std::size_t otherCols&gt;
      Matrix&lt;ROWS, COLS + otherCols, BackingType&gt; AugmentRight(const Matrix&lt;otherRows, otherCols, BackingType&gt;&amp; other)
      {
          static_assert(ROWS == otherRows, "Rows must match for a vertical augmentation.");
          Matrix&lt;ROWS, COLS + otherCols, BackingType&gt; result;
          for (std::size_t curRow = 0; curRow &lt; ROWS; ++curRow)
          {
              for (std::size_t curCol = 0; curCol &lt; COLS; ++curCol)
              {
                  result.Member(curRow, curCol) = Member(curRow, curCol);
              }
              for (std::size_t curCol = COLS; curCol &lt; (COLS + otherCols); ++curCol)
              {
                  result.Member(curRow, curCol) = other.Member(curRow, curCol - COLS);
              }
          }
          return result;
      }
      static Matrix&lt;ROWS, COLS, BackingType&gt; Identity()
      {
          static_assert(ROWS == COLS, "Identity matrices are always square.");
          Matrix&lt;ROWS, COLS, BackingType&gt; result;
          for (std::size_t diagonal = 0; diagonal &lt; ROWS; ++diagonal)
          {
              result.Member(diagonal, diagonal) = 1;
          }
          return result;
      }
  };
  
  template &lt;std::size_t leftRows, std::size_t leftCols, std::size_t rightRows, std::size_t rightCols, typename BackingType&gt;
  inline Matrix&lt;leftRows, rightCols, BackingType&gt; operator*(const Matrix&lt;leftRows, leftCols, BackingType&gt;&amp; left, const Matrix&lt;rightRows, rightCols, BackingType&gt;&amp; right)
  {
      static_assert(leftCols == rightRows, "Matrix multiplications require that the left column count and the right row count match.");
      Matrix&lt;leftRows, rightCols, BackingType&gt; result;
      for (std::size_t i = 0; i &lt; leftRows; ++i)
      {
          for (std::size_t j = 0; j &lt; rightCols; ++j)
          {
              BackingType curItem = 0;
              for (std::size_t k = 0; k &lt; leftCols; ++k)
              {
                  curItem += left.Member(i, k) * right.Member(k, j);
              }
              result.Member(i, j) = curItem;
          }
      }
      return result;
  }
  
  template &lt;std::size_t rows, std::size_t cols, typename BackingType&gt;
  inline Matrix&lt;rows, cols, BackingType&gt; operator*(BackingType val, const Matrix&lt;rows, cols, BackingType&gt;&amp; target)
  {
      Matrix&lt;rows, cols, BackingType&gt; result = target;
      for (std::size_t i = 0; i &lt; rows; ++i)
      {
          for (std::size_t j = 0; j &lt; cols; ++j)
          {
              result *= val;
          }
      }
      return result;
  }
  </code></pre>