Search code examples
visual-c++compatibilityvisual-studio-2012

Why the bad_alloc(const char*) was made private in Visual C++ 2012?


I am just trying to compile a bit bigger project using the Visual Studio 2012 Release Candidate, C++. The project was/is compiled using the VS2010 now. (I am just greedy to get the C++11 things, so I tried. :)

Apart of things that I can explain by myself, the project uses the code like this:

ostringstream ostr;
ostr << "The " __FUNCTION__ "() failed to malloc(" << i << ").";
throw bad_alloc(ostr.str().c_str());

The compiler now complains

error C2248: 'std::bad_alloc::bad_alloc' : cannot access private member declared 
    in class 'std::bad_alloc'

... which is true. That version of constructor is now private.

What was the reason to make that version of constructor private? Is it recommended by C++11 standard not to use that constructor with the argument?

(I can imagine that if allocation failed, it may cause more problems to try to construct anything new. However, it is only my guess.)

Thanks, Petr


Solution

  • The C++11 Standard defines bad_alloc as such (18.6.2.1):

    class bad_alloc : public exception {
    public:
        bad_alloc() noexcept;
        bad_alloc(const bad_alloc&) noexcept;
        bad_alloc& operator=(const bad_alloc&) noexcept;
        virtual const char* what() const noexcept;
    };
    

    With no constructor that takes a string. A vendor providing such a constructor would make the code using it not portable, as other vendors are not obliged to provide it.

    The C++03 standard defines a similar set of constructors, so VS didn't follow this part of the standard even before C++11. MS does try to make VS as standard compliant as possible, so they've probably just used the occasion (new VS, new standard) to fix an incompatibility.

    Edit: Now that I've seen VS2012's code, it is also clear why the mentioned constructor is left private, instead of being completely removed: there seems to be only one use of that constructor, in the bad_array_new_length class. So bad_array_new_length is declared a friend in bad_alloc, and can therefore use that private constructor. This dependency could have been avoided if bad_array_new_length just stored the message in the pointer used by what(), but it's not a lot of code anyway.