An exception-safe wrapper for std::stoi std::stoi may throw exceptions so it needs to be surrounded by try/catch.

In applications where std::stoi may be used frequently, it could be useful to have a wrapper.

Is this good practice?

int _stoi(std::string str, int* p_value) {
    // wrapping std::stoi because it may throw an exception

    try {
        *p_value = std::stoi(str);
        return 0;
    }

    catch (const std::invalid_argument&amp; ia) {
        //std::cerr &lt;&lt; "Invalid argument: " &lt;&lt; ia.what() &lt;&lt; std::endl;
        return -1;
    }

    catch (const std::out_of_range&amp; oor) {
        //std::cerr &lt;&lt; "Out of Range error: " &lt;&lt; oor.what() &lt;&lt; std::endl;
        return -2;
    }

    catch (const std::exception&amp; e)
    {
        //std::cerr &lt;&lt; "Undefined error: " &lt;&lt; e.what() &lt;&lt; std::endl;
        return -3;
    }
}
This wrapper effectively removes some of the available functionality from std::stoi() because its signature is

int stoi(const std::string&amp; str, std::size_t* pos = 0, int base = 10);


Because your wrapper does not allow a pos or base argument you cannot use it to give you the number of characters processed (with pos) nor to convert using a different base. std::stoi() provides default values for these arguments so you'd only have to provide them if you need the non-default behavior.

Also, you don't take the std::string argument by const reference like std::stoi() -- the string argument is probably not too expensive to copy in this context but why not accept the argument the same way std::stoi() does?

For completeness, I would also implement the overload of std::stoi() which accepts a std::wstring (and possibly std::stol() and std::stoll()).

I would also avoid the leading underscore, as identifiers with a leading underscore are reserved.

With these suggestions the wrapper would be implemented as

int stoi(const std::string&amp; str, int* p_value, std::size_t* pos = 0, int base = 10) {
    // wrapping std::stoi because it may throw an exception

    try {
        *p_value = std::stoi(str, pos, base);
        return 0;
    }

    catch (const std::invalid_argument&amp; ia) {
        //std::cerr &lt;&lt; "Invalid argument: " &lt;&lt; ia.what() &lt;&lt; std::endl;
        return -1;
    }

    catch (const std::out_of_range&amp; oor) {
        //std::cerr &lt;&lt; "Out of Range error: " &lt;&lt; oor.what() &lt;&lt; std::endl;
        return -2;
    }

    catch (const std::exception&amp; e)
    {
        //std::cerr &lt;&lt; "Undefined error: " &lt;&lt; e.what() &lt;&lt; std::endl;
        return -3;
    }
}