c++ - poder - arbitrario wikipedia
¿Plegar expresiones con arbitrario invocable? (2)
En primer lugar, estoy contento de que lo que escribí funciona en clang (veo que tu actualización implementa 3 de los 4 pasos que menciono). Tengo que dar crédito a Nick Athanasiou por esta técnica que discutió esto conmigo antes de escribir this .
La razón por la que menciono esto ahora es porque me informaron que lanzó una library (en la incubator biblioteca de impulso) que implementa estas cosas; puedes encontrar documentación relacionada here . Parece que la idea inicial (que los dos usamos aquí) y el código permitido de esta manera:
(Op<Max>(args) + ...); // Op is a function producing the custom fold type
se dejó de lado a favor de la evaluación perezosa y operadores con estado (o no incluidos aún, no se puede saber con certeza).
Mirando el documento C ++ 17 sobre pliegues, (y sobre cppreference ), estoy confundido acerca de por qué se hizo la elección de trabajar solo con operadores? A primera vista parece que sería más fácil expandir (... + args)
simplemente colocando un token +
entre los elementos de args
, pero no estoy convencido de que sea una gran decisión.
¿Por qué una expresión lambda binaria no puede funcionar tan bien y sigue la misma expansión que la anterior? Me resulta desagradable que se agregue una sintaxis de pliegue a un idioma sin soporte para callables arbitrarios, por lo que la sintaxis permite una forma de usarlos que simplemente no veo.
Actualización: Esto funciona para una función min()
variable min()
con clang
template <typename T>
struct MinWrapper {
const T& obj;
};
template <typename T, typename U, typename V=std::common_type_t<T,U>>
constexpr MinWrapper<V> operator%(
const MinWrapper<T>& lhs, const MinWrapper<U>& rhs) {
return {lhs.obj < rhs.obj ? lhs.obj : rhs.obj};
}
template <typename... Ts>
constexpr auto min(Ts&&... args) {
return (MinWrapper<Ts>{args} % ...).obj;
}
Es un excelente trabajo y una función de lenguaje glorioso. Si eludimos la conversación estándar, que no me gusta especialmente, me gustaría proponer una solución alternativa . Como no tengo un compilador de c ++ 17 (o una máquina del tiempo), mi respuesta solo describirá, lo que creo que podría ser, una solución para proporcionar expresiones plegables con funciones arbitrarias con el estado del idioma como está.
1. Defina un envoltorio de tipo (uno liviano)
template<typename T>
struct wp {
T const& val;
// yes there should be constructors
};
2. Maquinaria para transformar paquetes en paquetes envueltos
template<typename Op, typename Ts...>
using wrapped_pack = make_wrapped<Op, Ts..>
3. Sobrecarga un operador integrado para wp<T>
template<typename T, typename U>
ret_val operator+(wp<T> const& lhs, wp<U> const& rhs) {...}
4. Usa el paquete envuelto en la expresión doble
Esto requeriría una capa adicional donde los argumentos del pliegue se transforman en argumentos envueltos
Una deficiencia obvia de lo anterior es que no garantiza la exclusividad (o escalabilidad): cada pliegue con un functor personalizado consumiría una sobrecarga del operador incorporada.
Debería haber hacks para variar los tipos en función de la expresión en la que se encuentran, pero no quiero sumergirme tan profundamente en un experimento mental (por ejemplo, usar el tipo de Op
en el tipo de envoltorio ya da mucho más espacio para escalar en).