You are doing cargo-cult SFINAE. By this, I mean you are using SFINAE patterns to pull off what you need, and not understanding why you are doing those patterns.
This usually isn't all that bad. SFINAE is sort of insane, as an accidental feature that leaked into the language and gave us Turing-complete overload resolution. I mean, last I checked, the fact it worked with template class specialization isn't actually in the standard.
So following existing patterns to make it look reasonable is a good plan.
When you want to do something new, however, you have to understand what is actually going on.
template <typename T>
using Foo = std::enable_if_t<std::is_same_v<T, int>>;
this is a template alias that results in the type void if T passes the test, and in a substitution failure if T fails the test.
// Fine - accepts only ints
template <typename T, typename = Foo<T>>
void FooIt(T t) {}
your comment is a bit wrong. FooIt<double, void> works fine here.
What is going on here is that your default type argument produces a substitution failure if T is not an int. If T is an int, the default value for the 2nd type argument is void.
template <typename T,
// This does not work
typename = std::enable_if_t<Bar<T>::value || Foo<T>::value>>
void FooOrBarIt(T t) {}
of course it doesn't.
There is no ::value on the type void. Bar<T> is either void or a substitution failure, and the same for Foo<T>.
Neither supports ::value. So you get an error.
Your Foo<T> and Bar<T> are not a great pattern. But you stated you want to keep them.
So what I'd start with is this:
template<class T, template<class>class Z, class=void, template<class>class...Zs>
struct test{};
template<class T, template<class>class Z>
struct test<T,Z,Z<T>>{
using type=void;
};
template<class T,
template<class>class Z0,
template<class>class Z1,
template<class>class...Zs
>
struct test<T, Z0, Z0<T>, Z1, Zs...>:
test<T, Z1, void, Zs...>
{};
template<class T, template<class>class Z0, template<class>class...Zs>
using test_t = typename test<T, Z0, void, Zs...>::type;
now test_t can be used to fuze your traits.
template <typename T,
typename = test_t<T, Bar, Foo>>
void FooOrBarIt(T t) {}
in a way you are familiar with.
Digression
Note that this style of SFINAE has problems where you can't use it to dispatch between two overloads of FooOrBarIt. Ie,
template<class T, class=Bar<T>>
void bob(T) {}
template<class T, class=Foo<T>>
void bob(T) {}
this results in an overload resolution error.
Another cargo-cult pattern:
template<class T>
using Bar = std::enable_if_t<std::is_same_v<T,int>, bool>;
template<class T>
using Foo = std::enable_if_t<std::is_same_v<T,double>, bool>;
template<class T, Bar<T> =true>
void bob(T) {}
template<class T, Foo<T> =true>
void bob(T) {}
looks slightly different, but permits the two bob overloads above to work.
For that variant, you'd have to change how you joined them:
template<Ts...>
using AllTraits = bool;
template <typename T,
AllTraits<Foo<T>, Bar<T>> = true>
void FooOrBarIt(T t) {}
note that the =true in this particular cargo cult version is not a test; =false would produce the exact same results.