domingo, 2 de setembro de 2012

Asserções Estáticas (em tempo de compilação) em C++11

Nos próximos posts vamos explorar algumas novidades do novo padrão do C++: o C++11. Vamos começar por asserções estáticas.

Uma asserção é teste que garante a corretude do código. C++ já possuía asserções, contidas na <cassert>, que poderiam ser ativadas só no modo de debug. A vantagem das asserções estáticas é que elas são executadas em tempo de compilação, não acarretando nem prejuízo em performance. Elas podem ser usadas, por exemplo, para garantir certas propriedades estáticas de classes usadas por clientes.

Como exemplo, vamos implementar uma classe que contenha um número. Queremos garantir que somente tipo numéricos vão poder ser usados como parâmetro.
class Function{
template <typename T>
class Number {
  T number_;
public:
  Number(T number) : number_(number) {
    // flags a compilation error if experession is false
    static_assert(std::is_arithmetic<T>::value,
                            "type must be a number"); 
  }
};
Na linha 8 temos o static_assert, que recebe dois parâmetros: a expressão, que deve ser verdadeira, e a mensagem de erro a ser exibida. Caso a expressão seja falsa, o código não vai compilar. Agora se usarmos um tipo int ou float, não teremos nenhum problema de compilação.
class B {

};

int main()
{
  double d;
  int i;
  B b;
  
  Number<double> cd(d); // OK, d is a floating-point number 
  Number<int> ci(i);    // OK, i is Integral
  Number<B> cb(b);    // Not OK, b is a class 
}
Mas se utilizarmos um tipo não-primitivo, teremos o seguinte erro:
static_assert.cpp: In constructor ‘Number<T>::Number(T) [with T = B]’:
static_assert.cpp:27:17:   instantiated from here
static_assert.cpp:11:5: error: static assertion failed: "type must be a number"
O código completo pode ser visto no github, em static_assert.cpp.

Nenhum comentário:

Postar um comentário