在我的项目中,我使用浮点数来处理大量的三维数学(因此方形矩阵和长度为4的向量)。当然我已经创建了类来帮助我,因为我已经使用数组作为成员的数据类型,我知道它们将被连续分配。没有虚拟,所以没有v-table指针,所以没有RTTI,我确实有一个断言,但是我会警告我。
现在我有类似的东西:(这是伪代码,显示哪些有效,但没有具体细节,为了简洁起见)
class program {
/*...*/
protected:
Vec4 point_pos;
protected:
program() {
register_var("pos",point_pos);
}
void prepare() {}
void run() {
point_pos.fill(0);
}
};
class specific_program: public program {
private:
Mat4x4 mvp;
Vec3 amb_dir;
Vec4 vertex;
Vec4as3<1> surface_norm;
/*
Vec4as3 may be assigned to by vec3s, takes the space of vec3;
but the 4th value is the template param
*/
Mat4x4 norm_trans;
public:
specific_program() {
register_var("a",mvp);
register_var("b",amb_dir);
register_var("c",surface_norm);
register_Var("d",vertex);
}
void prepare() {
norm_trans = Mat4::inverse(mvp).transpose();
}
void run() {
point_pos = mvp * vertex;
}
};
register_var
接受引用,并根据它找到地址,然后告诉系统&#34; heres你把这些数据放在哪里&#34;它会复制所需数量的花车。运行它然后研究结果。我想要做的是使用程序的结果(例如point_pos
和任何其他声明为输出的结果)但不是作为单独的块,我想要有一个浮点数组和将结构投影到它们上,例如:(假设我们有输出point_pos和point_colour)
float 0: point_pos.x
float 1: point_pos.y
float 2: point_pos.z
float 3: point_pos.w
float 4: point_colour.x
float 5: point_colour.y
float 6: point_colour.z
/*any floats left (if fixed size) unused*/
如果我可以处理浮动缓冲区,它会快得多。 (在上面,7个浮点数,而不是可能在内存中不连续的2个变量)。
现在在C ++ 11中你有比以前更强大的元编程,使用与元组相同的逻辑,我想要一个我可以这样使用的类:
data_buffer<Mat4x4,Vec4,Vec3> variables;
说。然后(最坏情况)访问:variables.get<0>()*variables.get<1>()
。
虽然这不是一个元组!编译器不能填充这些,它必须在浮点数组上强加结构。例如,start_of_floats+4
是上例中颜色向量的开头。它可以将此演员表返回Vec3&
。
&#34;更低&#34; (进一步远离代码结构)优化将确保这样的解决方案是有效的(至少对于GCC而言),因此在性能方面这很好。
我不确定如何使用模板执行此操作,该缓冲区指针的偏移量将来自模板参数,但我不确定如何获得Ts的sizeofs的总和进入模板的一个点。
您可以添加,更改或做的任何事情,以使这更好。我想使用对象,这是一个练习/实验,过去我使用了大量的宏而没有对象(在C中)来做这个。我希望看起来更漂亮,没有性能损失。
答案 0 :(得分:0)
如果我理解你的话,我会从这样的设计开始:
template<typename ElType, std::size_t N>
class SubArray
{
public:
typedef ElType value_type;
typedef ElType* iterator;
typedef const ElType* const_iterator;
typedef ElType& reference;
typedef const ElType& const_reference;
typedef typename std::iterator_traits<ElType*>::size_type size_type;
typedef typename std::iteartor_traits<ElType*>::difference_type difference_type;
explicit SubArray(ElType* ptr);
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
static constexpr size_type size() const;
reference operator[](size_type i);
const_reference operator[](size_type i) const;
private:
ElType* m_start;
};
template<typename T> class ArrayUserWithStorage;
template<typename ElType, std::size_t N>
class ArrayUser
{
protected:
typedef ElType element_type;
static constexpr std::size_t elements();
explicit ArrayUser(SubArray<ElType, N>);
SubArray<ElType, N>& storage();
const SubArray<ElType, N>& storage() const;
private:
SubArray<ElType, N> m_storage;
template <typename T>
friend class ArrayUserWithStorage<T>;
};
template <typename T>
struct ArrayUserWithStorage :
private std::array<typename T::element_type, T::elements()>,
public ArrayUser<typename T::element_type, T::elements()>
{
public:
template <typename... Args>
ArrayUserWithStorage(Args&& ... args) :
std::array(),
T(ArrayUser<typename T::element_type, T::elements()>(data()),
std::forward<Args>(args)...)
{}
};
class Vec3 : public ArrayUser<float, 3>
{
public:
explicit Vec3(SubArray<float, 3> storg);
Vec3(SubArray<float, 3> storg, float x, float y, float z) :
ArrayUser(storg)
{
storage()[0] = x;
storage()[1] = y;
storage()[2] = z;
}
// ...
};
typedef ArrayUserWithStorage<Vec3> LoneVec3;
template <typename ElType, typename... Ts>
class ArrayAsTuple
{
template <std::size_t NToAdd, typename... Us>
struct offset_helper
template <std::size_t Sum, typename... Us>
struct offset_helper<0, Us...>
{
static constexpr std::size_t offset = 0;
};
template <std::size_t NToAdd, typename U1, typename... Us>
struct offset_helper<NToAdd, U1, Us...>
{
static_assert(std::is_same<typename U1::element_type, ElType>::value,
"Mismatch in ArrayUser element types");
static constexpr std::size_t offset =
U1::elements() + offset_helper<NToAdd-1, Us...>::offset;
};
static constexpr total_elements = offset_helper<sizeof...(Ts), Ts...>::offset;
template <std::size_t I, typename... Us>
struct nth_type;
template <typename U1, typename... Us>
struct nth_type<0, U1, Us...>
{ typedef U1 type; };
template <std::size_t I, typename U1, typename... Us>
struct nth_type<I, U1, Us...>
{ typedef typename nth_type<I-1, Us...>::type type; };
std::array<ElType, total_elements> m_storage;
public:
using array_type = std::array<ElType, total_elements>;
ArrayAsTuple();
array_type& arr() &;
const array_type& arr() const &;
template<std::size_t N>
nth_type<N, Ts...> get() &;
{ return nth_type<N, Ts...>( m_storage.data() + offset_helper<N, Ts...>::offset ); }
};