Skoro pojęcia są zdefiniowane jako predykaty czasu kompilacji, czy możliwe jest również ponowne wykorzystanie tych predykatów dla algorytmów kompilacji? Czy na przykład można sprawdzić, czy wszystkie typy w krotce są zgodne z koncepcją? O ile widziałem, nie można w żaden sposób przekazać koncepcji do funkcji, co prowadzi mnie z powrotem do korzystania z szablonów w tych przypadkach.
#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>());
}
Chciałbym coś takiego, więc nie muszę cały czas owijać koncepcji, aby móc z niej skorzystać:
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>());
}
Czy jest jakiś sposób, aby się do tego zbliżyć?
all_types()
można znacznie uprościć za pomocą wyrażeń fold... &&
:return (... && Predicate::template test<Ts>());
Odpowiedzi:
Nie, nie bardzo. Nie w C ++ 20. W dzisiejszym języku nie ma pojęcia o szablonie-parametrze. Nawet szablonów zmiennych nie można używać jako parametrów szablonów. Więc jeśli mamy pomysł na początek, nie możemy uniknąć owijania.
Ale możemy zrobić prostsze opakowania. Jeśli zgodzimy się używać cech typu „starego stylu” jako predykatów, szczególnie tych, które zachowują się jak
std::integral_constant
s, wówczas możemy mieć dość zwięzłe definicje „koncepcyjne”, które mogą być używane jako predykaty.O ile mi wiadomo, jest tak dobry, jak to tylko możliwe.
źródło
Jeśli Twoim celem jest „sprawdzenie, czy wszystkie typy w krotce są zgodne z koncepcją” , możesz zrobić coś takiego:
DEMO NA ŻYWO
źródło
AllSame
variadic? Każdy parametr szablonu w pakiecie wprowadzony przez ograniczenie typu jest już osobno ograniczony.*_foo()
?...
naTs
i&& ...
że używa go. (Oczywiście nazwaAllSame
byłaby wtedy nieodpowiednia, ale nie jestem pewien, dlaczego i tak chciałbym wyrazić liczbę jednoznaczną<int,int,int>
).AllSame
aleSameAs
(patrz en.cppreference.com/w/cpp/concepts/same_as ), a OP chciał mieć koncepcję, która wymaga różnych parametrów szablonu.std::same_as
. Nie sądzę, by część variadyczna była istotna: była to (pożądana) zmienna tożsamość pojęcia. Chodziło mi o to, że wariantowy wariant twojego przykładu koncepcyjnego był nieistotny z punktu widzenia jego zastosowania (ponieważ koncepcje nie-variadyczne już działają z pakietami parametrów szablonu).