Как создать исключение <stdexcept> или <system_error> без выброса?

Исключения определены в<stdexcept> (например.std::logic_error, std::runtime_error и их подклассы, такие какstd::system_error) имеют конструкторы, ожидающие строковые аргументы, например:

domain_error(const string& what_arg);
domain_error(const char* what_arg);

с постусловиями

strcmp(what(), what_arg.c_str()) == 0
strcmp(what(), what_arg) == 0

соответственно. Не требуется, чтобы эти аргументы, передаваемые конструкторам, оставались действительными в течение срока действия этих исключений, поэтому единственный способ убедиться, что постусловия выполнены, - этодублировать и хранить эти динамические строки. Это требует памяти, поэтому я предполагаю, что их конструкция сама можетstd::bad_alloc или аналогичный, который обычносамый неожиданный, Это вызывает проблемы, потому что каждый пример кода, который я видел в дикой природе, побуждает людей писать код как

if (haveError)
    throw std::runtime_error("BOO!"); // May throw std::bad_alloc instead?!

тогда как, казалось бы, гораздо безопаснее заранее создать исключение в каком-то другом месте, например:

struct A {
    // During allocation of A one would often expect std::bad_alloc anyway:
    A() : m_someException("BOO!") {}
    void f() {
        /* Do stuff */
        if (haveError)
            throw m_someException;
            /* Note that according to §18.8.1.2 all standard library
               classes deriving from `std::exception` must have publicly
               accessible copy constructors and copy assignment operators
               that do not exit with an exception. In implementations such
               exception instances most likely share the common string
               with all their copies. */
    }
    std::runtime_error const m_someException;
};

Это заставляет меня очень осторожно относиться к библиотекам, которые выдают такие исключения, например, дажеregex_error от<regex> в C ++ 11 !!!

Почему в этих исключениях нет конструкторов no-throw / noexcept? Есть ли мнение об основных принципах C ++?

PS: Лично я бы ушелwhat() чистый абстрактный метод в этой точке в цепочке предков исключений.

РЕДАКТИРОВАТЬ 09.10.2017: Вот PoC, демонстрирующий, чтоstd::runtime_error строительство может броситьstd::bad_alloc вместо:

#include <cstddef>
#include <cstdlib>
#include <new>
#include <stdexcept>
#include <string>

bool throwOnAllocate = false;

void * operator new(std::size_t size) {
    if (!throwOnAllocate)
        if (void * const r = std::malloc(size))
            return r;
    throw std::bad_alloc();
}

void operator delete(void * ptr) { std::free(ptr); }

int main() {
    std::string const errorMessage("OH NOEZ! =(");
    throwOnAllocate = true;
    throw std::runtime_error(errorMessage);
}

Ответы на вопрос(4)

Ваш ответ на вопрос