Vincent Vincent - 1 month ago 11
C++ Question

Force narrowing conversion warning

Consider the following code that illustrates some narrowing conversions:

template <class T>
class wrapper
{
template <class> friend class wrapper;
public:
constexpr wrapper(T value)
: _data(value)
{}
template <class U>
constexpr wrapper(wrapper<U> other)
: _data(other._data)
{}
wrapper& operator=(T value)
{_data = value; return *this;}
template <class U>
wrapper& operator=(wrapper<U> other)
{_data = other._data; return *this;}
private:
T _data;
};

int main(int argc, char* argv[])
{
wrapper<unsigned char> wrapper1 = 5U;
wrapper<unsigned char> wrapper2{5U};
wrapper<unsigned char> wrapper3(5U);
wrapper<unsigned int> wrapper4 = 5U;
wrapper<unsigned int> wrapper5{5U};
wrapper<unsigned int> wrapper6(5U);
wrapper<unsigned char> wrapper7 = wrapper4; // Narrowing
wrapper<unsigned char> wrapper8{wrapper5}; // Narrowing
wrapper<unsigned char> wrapper9(wrapper6); // Narrowing
wrapper7 = wrapper4; // Narrowing
wrapper8 = wrapper5; // Narrowing
wrapper9 = wrapper6; // Narrowing
return 0;
}


How to change the body of the
wrapper
members, so that it triggers the compiler warning for narrowing conversion? My goal is to make the user aware that something is potentially wrong with their code.

Answer

When you actually have a narrowing conversion for the contained type, say from unsigned int to unsigned char, you can trigger a narrowing conversion with uniform initialization syntax:

class wrapper 
{   
    template <class> friend class wrapper;
    public:
        constexpr wrapper(T value)
        : _data{value} // note the curly brackets here
        {}
        template <class U>
        constexpr wrapper(wrapper<U> other)
        : _data{other._data}
        {}
        wrapper& operator=(T value)
        {_data = value; return *this;}
        template <class U>
        wrapper& operator=(wrapper<U> other)
        {_data = {other._data}; return *this;} // and here
    private:
        T _data;
};

with

wrapper<unsigned int> wrapper1 = 5U;
wrapper<unsigned char> wrapper2 = wrapper1;  // Narrowing
wrapper<unsigned char> wrapper3(wrapper1);  // Narrowing
wrapper<unsigned char> wrapper4{wrapper1};  // Narrowing
wrapper2 = wrapper1;  // Narrowing

any of the four last lines will produce a narrowing conversion warning.

Comments