Dado que los conceptos se definen como predicados en tiempo de compilación, ¿también es posible reutilizar estos predicados para algoritmos en tiempo de compilación? Por ejemplo, ¿sería posible verificar si todos los tipos de una tupla se ajustan a un concepto? Por lo que he visto, no es posible pasar un concepto a una función de ninguna manera, lo que me lleva de nuevo a usar plantillas para estos casos.
#include <type_traits>
template<typename T>
concept FloatLike = std::is_same_v<T, float>;
struct IsFloat
{
template<typename U>
constexpr static bool test()
{
return FloatLike<U>;
}
};
template<typename Predicate, typename... T>
constexpr bool all_types()
{
return (Predicate::template test<T>() && ...);
}
int main()
{
static_assert(all_types<IsFloat, float, float>());
static_assert(!all_types<IsFloat, float, int>());
}
Lo que me gustaría hacer es algo como esto, así que no tengo que envolver el concepto todo el tiempo para poder usarlo:
template<concept Predicate, typename... T>
constexpr bool all_types()
{
return (Predicate<T> && ...);
}
int main()
{
static_assert(all_types<FloatLike, float, float>());
static_assert(!all_types<FloatLike, float, int>());
}
¿Hay alguna forma de acercarse a esto?
all_types()
puede simplificarse significativamente usando expresiones de plegado... &&
:return (... && Predicate::template test<Ts>());
Respuestas:
Bueno, no, en realidad no. No en C ++ 20. Actualmente no existe una noción en el lenguaje de una plantilla concepto-parámetro. Incluso las plantillas variables no se pueden usar como parámetros de plantilla. Entonces, si tenemos un concepto para comenzar, no podemos evitar el ajuste.
Pero lo que podemos hacer es escribir envoltorios más simples. Si aceptamos usar rasgos de tipo "estilo antiguo" como predicados, específicamente aquellos que se comportan como
std::integral_constant
s, entonces podemos tener definiciones de "concepto" bastante concisas que pueden usarse como predicados.Es tan bueno como puede llegar , hasta donde puedo ver.
fuente
Si su objetivo es "verificar si todos los tipos en una tupla se ajustan a un concepto" , puede hacer algo como esto:
DEMO EN VIVO
fuente
AllSame
variadic? Cada parámetro de plantilla en un paquete introducido por una restricción de tipo ya está limitado por separado.*_foo()
?...
encendidoTs
y el&& ...
que lo usa. (Obviamente, el nombreAllSame
sería entonces inadecuado, pero no estoy seguro de por qué me gustaría expresar un recuento en unario como<int,int,int>
de todos modos.)AllSame
sinoSameAs
(ver en.cppreference.com/w/cpp/concepts/same_as ) y OP quería tener un concepto que tomara un número variable de parámetros de plantilla.std::same_as
. No creo que la parte variada fuera el punto: era la identidad variable (deseada) del concepto. Y mi punto fue que el aspecto variado de su ejemplo conceptual era irrelevante para su uso (porque los conceptos no variables ya funcionan con paquetes de parámetros de plantilla).