Estoy codificando una utilidad de limpieza que almacenará los elementos que se van a limpiar en una tupla y, en caso de una condición de error, realizará la acción adecuada para cada elemento de la tupla. Algunos de los elementos típicos de la tupla serían punteros a objetos que se asignaron en el montón. Cuando mi controlador de limpieza decide eliminar estos objetos, debe saber si debe usar la expresión de eliminación de vainilla o la forma de matriz de la expresión de eliminación (eliminar []). ¿Cómo haría para determinar si un elemento en la tupla es un puntero a un solo objeto o un puntero a una matriz de objetos?

Aquí hay una implementación de muestra. Y aquí están las secciones que son relevantes para esta pregunta:

template<unsigned index, typename... Types>
struct TupleItemDeleter
{
    void operator() (std::tuple<Types...>& t)
    {
        std::cout << "Deleting item at index " << index << std::endl;
        delete std::get<index>(t); //HOWTO: delete[] or delete?
        TupleItemDeleter<index - 1, Types...>{}(t);
    }
};

template<typename... Types>
struct TupleItemDeleter<0, Types...> 
{
    void operator() (std::tuple<Types...>& t)
    {
        std::cout << "Deleting item at index 0" << std::endl;
        delete std::get<0>(t); //HOWTO: delete[] or delete?
    }
};

template<typename... Types>
void deleter(std::tuple<Types...>& t)
{
    constexpr auto tupleSize = std::tuple_size<std::tuple<Types...>>::value;
    TupleItemDeleter<tupleSize - 1, Types...>{}(t);
}

PD: probé std :: is_array, no es útil en mi caso.

0
DigitalEye 21 feb. 2018 a las 04:25

2 respuestas

La mejor respuesta

No se puede decir solo con el puntero si apunta a un solo objeto o una matriz; por eso hay dos formas de delete, porque el compilador tampoco puede decirlo. Necesita rastrear la información de otra manera.

Como ya está usando una tupla, quizás pueda almacenar un indicador allí.

3
Mark Ransom 21 feb. 2018 a las 01:44

La pregunta que debe hacerse es cómo sabe el código actualmente que un puntero es a una matriz, es decir, ¿cómo sabe que puede indexar un puntero de manera segura y también por cuánto?

Si hay algún modelo para eso, incluso si es solo una convención y no está bien codificado, entonces necesita encontrar alguna manera de pasar esa convención a su tupla.

Una forma sería almacenar un par de puntero / miembro para aquellos elementos que necesitan la eliminación de la matriz, aunque no use el recuento, o crear un contenedor de puntero inteligente que también contenga el recuento y comenzar a usarlos en más de los código.

Otro pensamiento es que ciertas clases quizás siempre estén asignadas a arreglos y otras nunca. Puede escribir usted mismo un rasgo que le diga esto por comportamiento de clase, o puede agregar un destroy () a las clases que realizan la operación correcta en cada clase. También puede suponer que es probable que cualquier puntero a un tipo simple sea asignado a una matriz, por ejemplo, es probable que un puntero de carácter sea una cadena.

Si puede ser más agresivo al reemplazar el asignador de las clases, sin editar el código heredado, podría decidir que todos los operadores new () para las clases que tienen el problema realmente llamen al operador new con un conteo de 1; o que todos los operadores new () registren la dirección en una tabla hash. Si se encuentra la dirección, entonces debe usar la eliminación del operador.

1
Gem Taylor 21 feb. 2018 a las 15:44