Considere o seguinte cenário (comum) ao lidar com, por exemplo, OpenGL:
Você tem void glUseProgram(GLuint program);
, assim como uma série de outras funções que exigem GLuint
; mas não há glGetUint
, você está preso a glGetInteger
.
Então, digamos que você tem
class Foo() {
public:
Foo::Foo() {
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
}
private:
GLuint program;
void Bar();
};
Por literalmente mais de 10 anos em nosso projeto, tivemos um trecho de código semelhante e somente agora, sem realmente alterar a configuração, o compilador começou a reclamar sobre esta conversão específica:
error: implicit conversion changes signedness: 'GLint' (aka 'int') to 'GLuint' (aka 'unsigned int') [-Werror,-Wsign-conversion]
A solução é obviamente simples:
class Foo() {
public:
Foo::Foo() {
int _program;
glGetIntegerv(GL_CURRENT_PROGRAM, &_program);
program = static_cast<GLuint>(_program);
}
private:
GLuint program;
void Bar();
};
Mas a questão é: posso fazer a mesma coisa em apenas uma etapa, sem precisar usar um int de escopo local no meio?
Acho que não é possível (pelo menos não com gesso).
O problema é que
glGetIntegerv
espera um ponteiro para um assinadoGLint
(geralmente um alias paraint
), enquantoprogram
é um inteiro sem sinal .Teoricamente, você poderia se livrar do intermediário
int _program
usando uma conversão na chamada, algo como:Mas isso não vai funcionar (como @TedLyngmo demonstrou em um comentário abaixo ) porque você não pode usar
static_cast
fromunsigned*
paraint*
.reinterpret_cast
, mas eu ficaria longe disso o máximo possível para evitar armadilhas do UB.Resumindo:
acho que sua abordagem usando uma variável intermediária é uma boa solução.
No entanto, eu criaria
_program
umGLint
para corresponder corretamente à API (embora geralmente seja um alias para,int
de qualquer forma).você pode fazer como std::inout_ptr faz e criar o inline temporário, que é o mais próximo que você pode chegar de apenas pegar o ponteiro sem violar nenhuma regra do C++.
demonstração online