Como construir uma exceção <stdexcept> ou <system_error> sem lançar?

Exceções definidas em<stdexcept> (por exemplo.std::logic_error, std::runtime_error e suas subclasses comostd::system_error) têm construtores esperando argumentos de sequência, por exemplo:

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

com pós-condições

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

respectivamente. Não há exigência de que esses argumentos transmitidos aos construtores permaneçam válidos durante o tempo de vida dessas exceções; portanto, a única maneira de garantir que as pós-condições sejam mantidas é:duplicado e armazene essas seqüências dinâmicas. Isso requer memória, por isso suponho que a própria construção possa lançarstd::bad_alloc ou similar, que geralmente émais inesperado. Isso causa problemas, porque todo exemplo de código que eu vi na natureza incentiva as pessoas a escrever código como

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

considerando que seria muito mais seguro construir a exceção antecipadamente em outro local, por exemplo:

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;
};

Isso me deixa muito cauteloso com as bibliotecas que lançam essas exceções, por exemplo, mesmoregex_error de<regex> em C ++ 11 !!!

Por que essas exceções não têm construtores no-throw / noexcept? As diretrizes principais do C ++ têm algo a dizer sobre isso?

PS: Pessoalmente, eu teria deixadowhat() um método abstrato puro neste ponto da cadeia de ancestrais de exceção.

EDIT 09.10.2017: Aqui está um PoC demonstrando questd::runtime_error construção pode lançar umstd::bad_alloc em vez de:

#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);
}

questionAnswers(4)

yourAnswerToTheQuestion