A variant wants to reject duplicate alternatives; a tuple-like API wants to check that the requested type is actually inside. Both reduce to the same two questions about a pack — asked and answered entirely at compile time.
Two compile-time queries over a type pack: contains_v<T, Ts...> — is T among Ts; count_v<T, Ts...> — how many times. The first parameter is the needle, the rest is the haystack.
std::is_same_v<T, Ts> gives a pack of bools. Fold it with || for contains.
For count, a bool casts to 0 or 1 — fold the casts with +. Give the empty pack an explicit init value in the fold.
Hit Submit (or ⌘/Ctrl + ↵) — test results will show up here.