// El molde para pedir un bloque y llenarlo sin fugas, aunque una copia falle.
#include <cstddef>
#include <iostream>
#include <stdexcept>
#include <string>

// Lanza una excepción si la cadena de origen está vacía, para poder probar el camino del error.
std::string checked_copy(const std::string& text) {
    if (text.empty()) {
        throw std::runtime_error("cadena vacía");
    }
    return text;
}

// Quien llama es owner del bloque que recibe.
std::string* copy_block(const std::string* source, std::size_t count) {
    std::string* fresh = new std::string[count];
    try {
        for (std::size_t i = 0; i < count; i++) {
            fresh[i] = checked_copy(source[i]);
        }
    } catch (...) {
        delete[] fresh;
        throw;
    }
    return fresh;
}

int main() {
    const std::string good[] = {"ana", "beto"};
    std::string* block = copy_block(good, 2);
    std::cout << "copió " << block[0] << " y " << block[1] << "\n";
    delete[] block;

    const std::string bad[] = {"ana", ""};
    try {
        block = copy_block(bad, 2);
        delete[] block;
    } catch (const std::runtime_error& error) {
        std::cout << "excepción: " << error.what() << "; el bloque nuevo ya se liberó\n";
    }
    return 0;
}
