En la versión C++11 se agregó la característica de poder inicializar objetos usando las llaves. Esta sintaxis sirve tanto para objetos como para datos primitivos: enteros, flotantes, double

int i {0}
double pi{3.1416}
string mensaje{"Hola mundo"}
Coordenada2D origen{0, 0};

Este tipo de inicialización se llama inicialización uniforme y una de las cosas importantes que introduce es que no permite la conversión implicita entre tipos.

int pi = 3.1416; //No lanza error al compilar. Solo usará 3, que es la parte entera.
int pi {3.1416}; //Lanzará un error al compilar, no se puede convertir un número
flotante en entero.

El fragmento de código anterior es válido y compila sin ningún tipo de warning. La variable pi tendrá como valor el entero tres. Veamos otro ejemplo inocente.

class EnteroSinSigno {
    public:
        EnteroSinSigno(unsigned int e): e(e) {}
        unsigned int e;
};
...
EnteroSinSigno e(-1);

Pues sí, este código es perfectamente válido y compila sin lanzar ningún warning por que se está realizando una conversión implícita por debajo. Es evidente que no deberia compilar, el constructor espera un entero sin signo y estamos construyendo el objeto con nada menos que un número negativo.

La solución es habituarnos a inicializar las variables usando las llaves. De esta manera el compilador si que devuelve un error y nos tira a la cara el error que estamos cometiendo:

EnteroSinSigno e{-1}; //narrowing conversion of ‘-1’ from ‘int’ to ‘unsigned int’[-Wnarrowing]

Enlaces

http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-narrowing