我想编写一个模板函数,它可以使用std::vector
将数据传递给C风格的API(在我的用例中专门用于OpenGL)。我想出的代码如下:
template<typename T>
void pass_data(GLuint buffer, std::vector<T> const& data) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(T), data.data(), GL_STATIC_DRAW);
}
这似乎是一个简单的解决方案,直到我发现T
可能有对齐限制会导致&t[1] - &t[0] != sizeof(T)
为真,这意味着此函数无法准确传递整个数组。所以我改写了这个函数来代替:
template<typename T>
void pass_data(GLuint buffer, std::vector<T> const& data) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, static_cast<size_t>(&data[data.size()] - &data[0]), data.data(), GL_STATIC_DRAW);
}
但是,我不清楚这种过去一次访问是否安全(我非常确定它的未定义行为)。确保我的函数准确评估向量的字节大小,并将正确的参数传递给基础C-API调用的最佳方法是什么?
注意:我不想讨论我如何[错误]使用OpenGL。我只关注精确建模指针+矢量大小的愿望。
答案 0 :(得分:4)
是的,data[data.size()]
是未定义的行为。
幸运的是,您不需要任何此类内容,因为(char*)&data[1] - (char*)&data[0] == sizeof(T)
实际上保证适用于任何类型T
。所以回到data.size() * sizeof(T)
。
但我还要添加一个
static_assert(std::is_trivially_copyable<T>::value, "Invalid type");
更安全一点。