Home > Enterprise >  Non-constant-expression cannot be narrowed from type 'unsigned long' to 'int' in
Non-constant-expression cannot be narrowed from type 'unsigned long' to 'int' in

Time:01-07

please help a c newbie understand what is going wrong here. I got compile error message of Non-constant-expression cannot be narrowed from type 'unsigned long' to 'int' in initializer list on leetcode web and my local ubuntu terminal, but it works perfectly fine on my CLion IDE. Also could explain why I got the error and how to solve it?

#include <iostream>
#include <bits/stdc  .h>
using namespace std;

int main()
{
    vector<vector<int>> heights({{1, 2, 2, 3, 5}, {3, 2, 3, 4, 4}, {2, 4, 5, 3, 1}, {6, 7, 1, 4, 5}, {5, 1, 1, 2, 4}});
    deque<vector<int>> dq;

    for (int i=0;i<heights.size();i  ){
        dq.push_back({i,heights[0].size()-1});
    }


    for (auto vec: dq){
        if (vec.empty())
            cout<< "vec is empty";
        else
            cout<<vec[0]<< " "<< vec[1]<<endl;
    }
    return 0;
}

Soon as switch to pair from vector<int>, the error is gone. It's quite confusing to a newbie like me. Please shed some light on this.

#include <iostream>
#include <bits/stdc  .h>
using namespace std;

int main()
{
    vector<vector<int>> heights({{1, 2, 2, 3, 5}, {3, 2, 3, 4, 4}, {2, 4, 5, 3, 1}, {6, 7, 1, 4, 5}, {5, 1, 1, 2, 4}});
    deque<pair<int, int>> dq;

    for (int i=0;i<heights.size();i  ){
        dq.push_back({i,heights[0].size()-1});
    }


    for (auto [u,v]: dq){
        cout<<u<< " "<< v<<endl;
    }
    return 0;
}

CodePudding user response:

When you use brace-initialization, it is forbidden for a narrowing conversion to be used to convert from the type of the value in the braced list to the type that the constructor actually requires. heights[0].size()-1 has type size_t, and the constructor of std::vector<int> takes std::initializer_list<int>. Usually, int cannot represent all values of type size_t, which means that size_t to int is a narrowing conversion. You can fix this using an explicit cast:

dq.push_back({i,static_cast<int>(heights[0].size()-1)});

When the type being constructed is std::pair<int, int>, it is a different story. No conversion actually occurs when calling the constructor; instead, the following constructor is called:

template< class U1, class U2 >
constexpr pair( U1&& x, U2&& y );

See cppreference.

Internally, presumably in the constructor initializer list, the constructor will convert size_t to int, but this will not be done inside braces, so it's legal.

CodePudding user response:

C language doesn't allow narrowing implicit conversions within a braced initialiser list (unless the value compile time constant). This protects you from making certain obvious mistakes.

This is the braced initialiser list: {i,heights[0].size()-1}.

A narrowing conversion is a conversion into a type that cannot represent all values of the source type. The type of the expression heights[0].size()-1 was on your system unsigned long which on your system can represent values that the int type cannot represent.

You can fix the issue by doing an explicit conversion. It is safe in this case because we know that the size is non-zero, and doesn't exceed the maximum value representable by int:

static_cast<int>(heights[0].size()-1)
  •  Tags:  
  • Related