Search code examples
c++constructortype-conversion

how to enable narrowing conversion in function parameter


how to enable narrowing conversions in functions or constructors, that is you're allowed to pass types that require narrowing conversion, without the need to use static_cast explicitly

struct Position
{
    float x;
    float y;
    Position(float x, float y) : x{ x }, y{ y } {}
};
Position p{1, 1};

Solution

  • Note: I do not endorse this approach, but at the same time I think there is value in knowing it.

    The warning about a narrowing conversion is legitimate (it is a potential bug), so it should be handled somewhere. If you do not want users of your class to worry about it, you can add constructors to cover all scenarios and put the casts in your constructors.

    #include <type_traits>
    
    struct Position
    {
        float x;
        float y;
    
        template <class Number> requires std::is_arithmetic_v<Number>
        Position(Number x, Number y) :
            x{ static_cast<float>(x) }, y{ static_cast<float>(y) }
        {}
    };
    

    Of course, with this approach, it's on you if these casts cause bugs. This might be acceptable in a stand-alone program, but I would strongly advise against it for re-usable (library) code.


    A better approach is to normalize the types used to store coordinates. If your choice is float, you could make an alias for that to give this choice semantic weight.

    using Coordinate = float;
    
    struct Position
    {
        Coordinate x;
        Coordinate y;
    
        Position(Coordinate x, Coordinate y) : x{ x }, y{ y } {}
    };
    

    With this approach, if Coordinate is used consistently when calculating coordinates, a narrowing conversion is an even more likely sign of an error that should be addressed rather than papered over.

    The choice is yours. Suppress warnings and risk bugs, or respect the warnings and have a better chance at bug-free code.