glGetShaderInfoLog to std::string?

c++, opengl, string

Solution

Both `string::c_str()` and `string::data()` return a `const char*` until C++17. Since C++17, `string::data()` has an overload that will return a `char*`. This means this code snippet is invalid.

Edit: An easier and as efficient solution is to use `&str[0]`. The subscript operator will return a `char&`.

If you cannot use C++17, you could use a `std::vector<char>`, which does have a non-const `data()`, but this will cause a copy when constructing a `std::string`:

// ...
std::vector<char> v(log_length);
glGetShaderInfoLog(fs, log_length, NULL, v.data());
std::string s(begin(v), end(v));

Also, `reserve()` isn't sufficient, because the actual `size()` is not changed. If `c_str()` returned a `char*`, the snippet would actually also cause undefined behavior.

Problem

This is a snippet from OpenGL Super Bible 7th edition: ``` GLint log_length; glGetShaderiv(fs, GL_INFO_LOG_LENGTH, &log_length); std::string str; str.reserve(log_length); glGetShaderInfoLog(fs, log_length, NULL, str.c_str()); ``` At a first glance it seemed weird to me to pass `str.c_str()` as an argument to this function, and of course clang immediatelly protested: `cannot initialize a parameter of type 'GLchar *' (aka 'char *') with an rvalue of type 'const char *'`. So I tried to investigate and changed `str.c_str()` to `str.data()`, which should provide a pointer to the internal data array, but this produces the same error message. Edit: `c_str()` and `data()` are actually the same thing (in c++11 at least), so it doesn't matter which one we use. I did some searches, but didn't find a solution (although I'm quite new to C++ and some things are still not obvious to me). Is this an error in the book? And is there a way to make it work with std::string?

Original source