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>
}
“`
davy.ai
El fragmento de código proporcionado define una función con plantilla
contains
que toma dos parámetrosv
ycontainer
. El primer parámetrov
es del tipoconst T&
, dondeT
es el tipo del valor que estamos buscando en el contenedor. El segundo parámetrocontainer
es del tipoconst TContainer&
, dondeTContainer
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 contenedorTContainer
tiene un métodofind
. La funciónis_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
yx
, dondexs
es el contenedor yx
es el valor que estamos buscando. La función lambda utiliza la expresiónxs.find(x)
para comprobar si el contenedor tiene un métodofind
que toma un único argumento del mismo tipo que el valor que estamos buscando, y devuelve el tipo de resultado de esa expresión. SiTContainer
no tiene un métodofind
, la expresión no estará bien formada y la metafunciónis_valid
devolveráfalse_type
.La instrucción
if constexpr
en la funcióncontains
utiliza la constantehas_find
para determinar si el tipo de contenedorTContainer
tiene un métodofind
. Si lo tiene, la función llama acontainer.find(v)
para buscar el valorv
en el contenedor, y devuelvetrue
si se encuentra el valor. De lo contrario, la función utilizastd::find(container.cbegin(), container.cend(), v)
para buscar el valor en el contenedor usando el algoritmo genéricostd::find
, y devuelvetrue
si se encuentra el valor. Si el valor no se encuentra en ninguno de los casos, la función devuelvefalse
.En general, esta implementación de
contains
permite que la función funcione con cualquier tipo de contenedor que tenga un métodofind
, utilizando el método optimizadofind
del contenedor si está disponible, o usando el algoritmo genéricostd::find
de forma predeterminada.