發佈幾年之後,C++ 11授予了我們一些新的可能性。
這裏是一個的包括在我做飯了,應該給其他人誰在這個跌倒的現代化起點的OpenGL庫的早期草案:
(注 - 這還有待檢驗或審覈)
/*(KILLGPL: Incompatible with Libraries Linked to the GPL)
============================================================================
"Free software" should be just that - free. Extreme copy-left licenses
such as the GPL, GPL2, GPL3, etc, and their users have twisted the
term "free" to meet their own anti-business, anti-closed source agendas by
forcing licensees to relicense their software under the same "viral" terms
and by forcing licensees to distribute sources with binary distributions.
This license stands in protest of such licenses in an attempt to protect
the freedoms that extreme copy-left licenses have been taking away from
software developers for far too long.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software with only one restriction: no part of
it may be included in software projects that are distributed under "viral"
licensing schemes like those found in the GPL, GPL2, GPL3, etc.
There are no further usage restrictions. Licensees are encouraged to use
this software in both open and closed source applications, so long as no
part of the combined work is licensed under extreme copy-left licenses.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software. Note - this notice
does not have to appear in YOUR code, but must remain intact in the parts
licensed under the KILLGPL.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/
#ifndef MATRIX_HPP
#define MATRIX_HPP
#include <array>
#include <cstdint>
#include <iterator>
#include <initializer_list>
#include <iosfwd>
/// Forward Declarations Required for free-function friends
template<typename T, std::size_t X, std::size_t Y>
class Matrix;
/**
* Performs a component-wise comparison between the two provided matrices
*
* @param lhs the first matrix to compare
*
* @param rhs the second matrix to compare
*
* @return true if the two matrices are equal, otherwise false
*
*/
template<typename T, std::size_t X, std::size_t Y>
bool operator==(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept;
/**
* Performs a component-wise comparison between the two provided matrices
*
* @param lhs the first matrix to compare
*
* @param rhs the second matrix to compare
*
* @return true if the two matrices are not equal, otherwise false
*
*/
template<typename T, std::size_t X, std::size_t Y>
bool operator!=(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept;
/**
* Inserts the provided Matrix into the provided output stream
*
* @param stream the stream to insert the provided Matrix into
*
* @param matrix the Matrix to insert into the provided stream
*
* @return the provided stream
*
*/
template<typename T, std::size_t X, std::size_t Y>
std::ostream& operator<<(std::ostream& stream, const Matrix<T, X, Y>& matrix);
/**
* Extracts a Matrix from the provided input stream
*
* @param stream the stream to extract from
*
* @param matrix the Matrix to extract into
*
* @return the provided input stream
*
*/
template<typename T, std::size_t X, std::size_t Y>
std::istream& operator>>(std::istream& stream, Matrix<T, X, Y>& matrix);
/**
* A modern general-purpose object-oriented matrix class without any legacy hacks from C
*
* Several common matrix types are also defined in the following format:
*
* Matrix {number of rows} x {number of columns} {type abbreviation}
*
* where the predefined type abbreviations are:
* type - abbreviation
* --------------------------
* double - D
* float - F
* int64_t - L
* uint64_t - UL
* int32_t - I
* uint32_t - UI
* int16_t - S
* uint16_t - US
* int8_t - C
* uint8_t - UC
*
* example: Matrix3x3F - A tuple that holds 3x3 float elements
*
* User-defined matrix types are expected to follow the aforementioned format.
*
* @tparam T the type of data stored in this matrix
*
* @tparam Rows the number of rows in this matrix
*
* @tparam Columns the number of columns in this matrix
*/
template<typename T, std::size_t Rows, std::size_t Columns>
class Matrix
{
static_assert(Rows > 0, "The number of rows in a Matrix must be greater than zero");
static_assert(Columns > 0, "The number of columns in a Matrix must be greater than zero");
/// Privileged free-functions
friend std::ostream& operator<<<>(std::ostream&, const Matrix<T, Rows, Columns>&);
friend std::istream& operator>><>(std::istream&, const Matrix<T, Rows, Columns>&);
friend bool operator!=<>(const Matrix<T, Rows, Columns>&, const Matrix<T, Rows, Columns>&);
friend bool operator==<>(const Matrix<T, Rows, Columns>&, const Matrix<T, Rows, Columns>&);
/// The actual container that holds the elements of this Matrix
std::array<T, Rows * Columns> values;
public:
/// A convenience field that provides the total number of elements in this Matrix
static constexpr std::size_t Length = Rows * Columns;
/**
* Retrieves the identity-matrix
*
* @return the identity-matrix
*
*/
static constexpr Matrix IDENTITY() noexcept;
/**
* Retrieves the zero-matrix
*
* @return the zero-matrix
*
*/
static constexpr Matrix ZERO() noexcept;
/**
* Constructs a Matrix with each element initialized to zero
*
*/
constexpr Matrix() noexcept;
/**
* Constructs a Matrix whose elements are initialized to the provided array
*
* @param elements the array to initialize this Matrix with
*
*/
explicit constexpr Matrix(const std::array<T, Rows * Columns>& elements) noexcept;
/**
* Constructs a Matrix whose elements are initialized to the provided array
*
* @param elements the array to initialize this Matrix with
*
*/
explicit constexpr Matrix(std::array<T, Rows * Columns>&& elements) noexcept;
/**
* Constructs a Matrix whose elements are initialized with the provided values
*
* @param element the first value
*
* @param elements all subsequent values
*
* <pre>Matrix<int, 3, 3> matrix(1, 2, 3, 1, 2, 3, 1,2 ,3);</pre>
*
*/
template<typename ...E>
explicit constexpr Matrix(T element, E&&... elements) noexcept;
/**
* Retrieves a const reference to the element at the provided row and column
*
* @param row the row to access
*
* @param column the column to access
*
* @return the element at the provided row and column
*
*/
/*constexpr*/const T& operator()(std::size_t row, std::size_t column) const noexcept;
/**
* Retrieves a reference to the element at the provided row and column
*
* @param row the row to access
*
* @param column the column to access
*
* @return the element at the provided row and column
*
*/
/*constexpr*/T& operator()(std::size_t row, std::size_t column) noexcept;
// TODO: Global Free Functions for performing transformations
};
namespace detail
{
// thanks be to Cubbi @ cplusplus.com for enlightenment
template<int ...> struct sequence
{
};
template<int N, int ...S> struct sequence_generator : sequence_generator<N - 1, N - 1, S...>
{
};
template<int ...S> struct sequence_generator < 0, S...>
{
using type = sequence<S...>;
};
template<std::size_t X, std::size_t Y>
constexpr int get_element(std::size_t pos)
{
return pos % Y == pos/Y;
}
template <typename T, std::size_t Rows, std::size_t Columns, int ...S>
constexpr std::array<T, Rows * Columns> get_identity_array(sequence<S...>)
{
return std::array<T, Rows * Columns> {{ get_element<Rows, Columns>(S)... }};
}
}
template<typename T, std::size_t Rows, std::size_t Columns>
bool operator==(const Matrix<T, Rows, Columns>& lhs, const Matrix<T, Rows, Columns>& rhs) noexcept
{
for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i)
{
if(lhs[i] == rhs[i])
{
return true;
}
}
return false;
}
template<typename T, std::size_t Rows, std::size_t Columns>
bool operator!=(const Matrix<T, Rows, Columns>& lhs, const Matrix<T, Rows, Columns>& rhs) noexcept
{
for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i)
{
if(lhs[i] != rhs[i])
{
return true;
}
}
return false;
}
template<typename T, std::size_t Rows, std::size_t Columns>
Matrix<T, Rows, Columns> operator-(const Matrix<T, Rows, Columns>& source) noexcept
{
Matrix<T, Rows, Columns> rv(source);
for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i)
{
rv[i] *= -1;
}
return rv;
}
template<typename T, std::size_t Rows, std::size_t Columns>
constexpr Matrix<T, Rows, Columns> Matrix<T, Rows, Columns>::IDENTITY() noexcept
{
return Matrix{detail::get_identity_array<T, Rows, Columns>(typename detail::sequence_generator<Rows * Columns>::type())};
}
template<typename T, std::size_t Rows, std::size_t Columns>
constexpr Matrix<T, Rows, Columns> Matrix<T, Rows, Columns>::ZERO() noexcept
{
return Matrix{};
}
template<typename T, std::size_t Rows, std::size_t Columns>
constexpr Matrix<T, Rows, Columns>::Matrix() noexcept
{
}
template<typename T, std::size_t Rows, std::size_t Columns>
constexpr Matrix<T, Rows, Columns>::Matrix(const std::array<T, Rows * Columns>& values) noexcept : values(values)
{
}
template<typename T, std::size_t Rows, std::size_t Columns>
constexpr Matrix<T, Rows, Columns>::Matrix(std::array<T, Rows * Columns>&& array) noexcept : values(array)
{
}
template<typename T, std::size_t Rows, std::size_t Columns>
template<typename ...E>
constexpr Matrix<T, Rows, Columns>::Matrix(T first, E&&... elements) noexcept : values {{ first, std::forward<T>(static_cast<T>(elements))... }}
{
}
template<typename T, std::size_t Rows, std::size_t Columns>
/*constexpr*/const T& Matrix<T, Rows, Columns>::operator()(std::size_t row, std::size_t column) const noexcept
{
dynamic_assert(row >= 0 && row < Rows, "access violation (row index " << row << " out of range [" << Rows << "])");
dynamic_assert(column >= 0 && column < Columns, "access violation (column " << column << " out of range [" << Columns << "])");
return values[column * Rows + row];
}
template<typename T, std::size_t Rows, std::size_t Columns>
/*constexpr*/T& Matrix<T, Rows, Columns>::operator()(std::size_t row, std::size_t column) noexcept
{
dynamic_assert(row >= 0 && row < Rows, "access violation (row index " << row << " out of range [" << Rows << "])");
dynamic_assert(column >= 0 && column < Columns, "access violation (column " << column << " out of range [" << Columns << "])");
return values[column * Rows + row];
}
/// Built-in library matrix types
typedef Matrix<uint8_t, 2, 2> Matrix2x2UC;
typedef Matrix<uint8_t, 3, 3> Matrix3x3UC;
typedef Matrix<uint8_t, 4, 4> Matrix4x4UC;
typedef Matrix<int8_t, 2, 2> Matrix2x2C;
typedef Matrix<int8_t, 3, 3> Matrix3x3C;
typedef Matrix<int8_t, 4, 4> Matrix4x4C;
typedef Matrix<uint16_t, 2, 2> Matrix2x2US;
typedef Matrix<uint16_t, 3, 3> Matrix3x3US;
typedef Matrix<uint16_t, 4, 4> Matrix4x4US;
typedef Matrix<int16_t, 2, 2> Matrix2x2S;
typedef Matrix<int16_t, 3, 3> Matrix3x3S;
typedef Matrix<int16_t, 4, 4> Matrix4x4S;
typedef Matrix<uint32_t, 2, 2> Matrix2x2UI;
typedef Matrix<uint32_t, 3, 3> Matrix3x3UI;
typedef Matrix<uint32_t, 4, 4> Matrix4x4UI;
typedef Matrix<int32_t, 2, 2> Matrix2x2I;
typedef Matrix<int32_t, 3, 3> Matrix3x3I;
typedef Matrix<int32_t, 4, 4> Matrix4x4I;
typedef Matrix<uint64_t, 2, 2> Matrix2x2UL;
typedef Matrix<uint64_t, 3, 3> Matrix3x3UL;
typedef Matrix<uint64_t, 4, 4> Matrix4x4UL;
typedef Matrix<int64_t, 2, 2> Matrix2x2L;
typedef Matrix<int64_t, 3, 3> Matrix3x3L;
typedef Matrix<int64_t, 4, 4> Matrix4x4L;
typedef Matrix<float, 2, 2> Matrix2x2F;
typedef Matrix<float, 3, 3> Matrix3x3F;
typedef Matrix<float, 4, 4> Matrix4x4F;
typedef Matrix<double, 2, 2> Matrix2x2D;
typedef Matrix<double, 3, 3> Matrix3x3D;
typedef Matrix<double, 4, 4> Matrix4x4D;
#endif
你應該填寫'...'來清除一些答案中的混淆。 – GManNickG 2010-01-16 08:07:51
好通話;這足夠嗎? – anon 2010-01-16 08:19:08