Search code examples
c++castingnarrowing

Correct syntax for uniform initialization of temporary of type with space in name like unsigned int


I'm trying to pass x of type T to a function foo which expects unsigned int, and I'm not sure what T is because it's a typedef declared in some other module. Both foo and T are not something I can modify. I want compiler to warn me if narrowing happens. So I'm trying:

typedef int T;
void foo(unsigned int x);
void bar(){
    T x;
    foo(unsigned int{x});
}

unfortunately on gcc 9.2. this gives me a compile error:

<source>: In function 'void bar()':

<source>:5:9: error: expected primary-expression before 'unsigned'

     foo(unsigned int{x});

         ^~~~~~~~

Compiler returned: 1

If I change the offending line to:

    foo((unsigned int){x});

then the problem goes away, and I get a correct warning that narrowing takes place:

<source>: In function 'void bar()':

<source>:5:25: warning: narrowing conversion of 'x' from 'T {aka int}' to 'unsigned int' inside { } [-Wnarrowing]

     foo((unsigned int){x});

                         ^

Compiler returned: 0

Great! Unfortunatelly this syntax does not work on Visual Studio 2019 16.2.5, as I get: E0029 C4576 C2397 errors in this line. Of which C4576 is "a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax".

So what is the standard explicit type conversion syntax for this case? https://en.cppreference.com/w/cpp/language/explicit_cast says in point 5) that it must be single-word type. What if it is more than one word (long long, unsigned long int, etc.?)


Solution

  • In your case, you can just write unsigned instead of unsigned int. But a more general solution is to create a type alias:

    void bar(T x) {
        using U = unsigned int;
        foo(U{x});
    }