Saltar al contenido

¿Función con un tipo de retorno personalizado y las condiciones de retorno "falsas"?

Solución:

Hay tres enfoques generales:

  • Utilice excepciones. Esto es lo que hay en la respuesta de Betsabé.
  • Regreso std::optional<Cell> (o algún otro tipo que puede o no tener una Cell).
  • Regreso booly agregue un Cell & parámetro.

Cuál de estos es el mejor depende de cómo pretenda que se utilice esta función. Si el caso de uso principal pasa un segmento válido, entonces use excepciones por todos los medios.

Si parte del diseño de esta función es que se puede usar para saber si un segmento es válido, las excepciones no son apropiadas y mi opción preferida sería std::optional<Cell>. Es posible que aún no esté disponible en la implementación de su biblioteca estándar (es una característica de C ++ 17); que no, boost::optional<Cell> puede ser útil (como se menciona en la respuesta de Richard Hodges).

En los comentarios, en lugar de std::optional<Cell>, usuario que sugieres expected<Cell, error> (no C ++ estándar, pero propuesto para un estándar futuro, e implementable fuera del std espacio de nombres hasta entonces). Esta puede ser una buena opción para agregar alguna indicación de por qué no Cell se puede encontrar para el segment parámetro pasado, si hay varias razones posibles.

La tercera opción la incluyo principalmente para completar. No lo recomiendo. Es un patrón popular y generalmente bueno en otros idiomas.

¿Es esta función una consulta, que podría no encontrar válidamente la celda, o es un imperativo, donde se espera que se encuentre la celda?

Si es el primero, devuelve un puntero opcional (o que acepta valores NULL) a la celda.

Si es el último, lanza una excepción si no se encuentra.

Anterior:

boost::optional<Cell> CSV::Find(std::string segment) {
  boost::optional<Cell> result;
  // Search code here.
  return result;
}

Más tarde: como lo tienes.

Y, por supuesto, existe el enfoque basado en variantes de c ++ 17:

#include <variant>
#include <string>

struct CellNotFound {};
struct Cell {};

using CellFindResult = std::variant<CellNotFound, Cell>;


CellFindResult Find(std::string segment) {
  CellFindResult result { CellNotFound {} };

  // Search code here.
  return result;
}

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

void cellsAndStuff()
{
    std::visit(overloaded
    {
        [&](CellNotFound)
        {
            // the not-found code
        },
        [&](Cell c)
        {
            // code on cell found
        }
    }, Find("foo"));
}

La forma de C ++ de lidiar con fallas abyectas es definir una clase de excepción de la forma:

struct CSVException : std::exception{};

En tu función entonces throw uno de los de la rama de fallas:

Cell CSV::Find(std::string segment) {
  Cell result;
  // Search code here.
  if (fail) throw CSVException();
  return result;
}

Luego maneja el caso de falla con un try catch bloquear en el sitio de la llamada.

Sin embargo, si la rama de "falla" es un comportamiento normal (de hecho subjetivo, pero solo usted puede ser el juez de la normalidad), entonces imbuya algún tipo de indicador de falla en su interior. Cell, o incluso cambiar el tipo de retorno a std::optional<Cell>.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada.