Search code examples
c++implicit-conversion

How to avoid implicit conversion from char to int when using arithmetic operators


I have templated some code which I want to specialize for both int and char. In this code, I use the arithmetic operator operator+. When I compile using g++ (conversion warnings, warnings treated as errors) the compiler complains that my chars are implicitly converted to ints and every further assignment triggers a narrowing conversion warning.

Here is some basic code to reproduce this issue:

template<typename T>
T add(const T a, const T b)
{
    return a + b;
}

int main()
{
    const char a = 1;
    const char b = 2;

    const char c = add<char>(a, b); // a and b implicitely converted to int.
                                    // Assignement to c fails (narrowing)

    (void)c;

    return 0;
}

which you can compile (it should fail) using:

g++ -Wconversion -Werror main.cpp

I know that this is because the smallest built-in type for which operator+ is defined is int, so when you use smaller types, they silently get converted to fit the arguments.

I am looking for a way to avoid this and minimize casting. I know for example that I could cast the result the addition of a and b to char, but for additions with many terms, it soon becomes a mess to read.

How could I do this?


The error I get:

main.cpp:4:16: error: conversion to ‘char’ from ‘int’ may alter its value [-Werror=conversion]
     return a + b;
                ^
cc1plus: all warnings being treated as errors

Solution

  • So yeah, formally this is the case:

    ... arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvalue-to-rvalue conversion [...]

    But why would you want to change or avoid this behavior? If you do something like you suggested, and maybe cast the return value like this:

    template<typename T>
    T add(const T a, const T b)
    {
        return static_cast<T>(a + b);
    }
    

    than you're getting pretty quickly to the risk of integer overflow in the returned char due to its small size to begin with. Is there any reason for you to avoid the promotion in your scenario?