es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Utilizando boost::hana para verificar la existencia de un método.

Estoy tratando de crear una función de plantilla “contains” que funcione para cualquier contenedor siguiendo estos dos pasos:

  • Usando el método “find” propio del contenedor “.find(valor)” si existe (lo cual debería estar optimizado para ese contenedor específico)
  • Si no existe, usar “std::find(xs.cbegin(), xs.cend(), v)” como último recurso.

Parece que boost::hana ofrece una función “is_valid” o una función “sfinae” para comprobar eso, pero no fui capaz de entender cómo funcionan…

“`
template<typename tcontainer,="" typename="" t="">
bool
contains(
const T &v,
const TContainer &container)
{
constexpr auto has_find = boost::hana::is_valid([](auto &&xs, auto &&x) -> decltype((void)xs.find(x)) {});

<pre><code>if constexpr(has_find) {
return container.find(v) != container.cend();
} else {
return std::find(container.cbegin(), container.cend(), v) != container.cend();
}
</code></pre>

}
“`

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El fragmento de código proporcionado define una función con plantilla contains que toma dos parámetros v y container. El primer parámetro v es del tipo const T&, donde T es el tipo del valor que estamos buscando en el contenedor. El segundo parámetro container es del tipo const TContainer&, donde TContainer es el tipo del contenedor en el que estamos buscando.

    La función utiliza la metafunción is_valid de Boost-Hana para comprobar si el tipo de contenedor TContainer tiene un método find. La función is_valid toma un objeto invocable como argumento y devuelve una constante booleana que indica si la llamada estaría bien formada (sin llamar realmente al objeto invocable). En este caso, el objeto invocable es una función lambda que toma dos argumentos, xs y x, donde xs es el contenedor y x es el valor que estamos buscando. La función lambda utiliza la expresión xs.find(x) para comprobar si el contenedor tiene un método find que toma un único argumento del mismo tipo que el valor que estamos buscando, y devuelve el tipo de resultado de esa expresión. Si TContainer no tiene un método find, la expresión no estará bien formada y la metafunción is_valid devolverá false_type.

    La instrucción if constexpr en la función contains utiliza la constante has_find para determinar si el tipo de contenedor TContainer tiene un método find. Si lo tiene, la función llama a container.find(v) para buscar el valor v en el contenedor, y devuelve true si se encuentra el valor. De lo contrario, la función utiliza std::find(container.cbegin(), container.cend(), v) para buscar el valor en el contenedor usando el algoritmo genérico std::find, y devuelve true si se encuentra el valor. Si el valor no se encuentra en ninguno de los casos, la función devuelve false.

    En general, esta implementación de contains permite que la función funcione con cualquier tipo de contenedor que tenga un método find, utilizando el método optimizado find del contenedor si está disponible, o usando el algoritmo genérico std::find de forma predeterminada.

Comments are closed.