Puisque les concepts sont définis comme des prédicats au moment de la compilation, est-il également possible de réutiliser ces prédicats pour les algorithmes au moment de la compilation? Par exemple, serait-il possible de vérifier si tous les types d'un tuple sont conformes à un concept? Pour autant que je l'ai vu, il n'est pas possible de transmettre un concept à une fonction, ce qui me ramène à l'utilisation de modèles pour ces cas.
#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>());
}
Ce que je voudrais faire, c'est quelque chose comme ça, donc je n'ai pas à envelopper le concept tout le temps pour pouvoir l'utiliser:
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>());
}
Existe-t-il un moyen de se rapprocher de cela?
all_types()
peut être considérablement simplifié en utilisant des expressions de repli... &&
:return (... && Predicate::template test<Ts>());
Réponses:
Eh bien non, pas vraiment. Pas en C ++ 20. Il n'y a aucune notion dans le langage actuel d'un modèle-paramètre de modèle. Même les modèles de variables ne peuvent pas être utilisés comme paramètres de modèle. Donc, si nous avons un concept pour commencer, nous ne pouvons pas éviter le wrapping.
Mais ce que nous pouvons faire, c'est écrire des enveloppes plus simples. Si nous acceptons d'utiliser des traits de type "à l'ancienne" comme prédicats, en particulier ceux qui se comportent comme des
std::integral_constant
s, alors nous pouvons avoir des définitions de "concept" assez concises qui peuvent être utilisées comme prédicats.C'est aussi bon que possible , pour autant que je puisse voir.
la source
Si votre objectif est de "vérifier si tous les types d'un tuple sont conformes à un concept" , vous pouvez faire quelque chose comme ceci:
DÉMO EN DIRECT
la source
AllSame
variadic? Chaque paramètre de modèle dans un pack introduit par une contrainte de type est déjà contraint séparément.*_foo()
?...
leTs
et celui&& ...
qui l'utilise. (De toute évidence, le nomAllSame
serait alors inapproprié, mais je ne sais pas pourquoi je voudrais exprimer un décompte en unaire comme de<int,int,int>
toute façon.)AllSame
maisSameAs
(voir en.cppreference.com/w/cpp/concepts/same_as ) et OP voulait avoir un concept qui prend un certain nombre de paramètres variadique de modèle.std::same_as
. Je ne pense pas que la partie variadique était le point: c'était l' identité variable (souhaitée) du concept. Et mon point de vue était que l'aspect variadique de votre exemple de concept n'était pas pertinent pour son utilisation (car les concepts non variadiques fonctionnent déjà avec les packs de paramètres de modèle).