Suppose that we have a template like below, but we would prefer that it be variadic and we can automate the creation of the various operators that should be implemented - How do we approach this?

```
template <typename T1, typename T2, typename T3, typename T4>
class Foo { 
private:
    boost::variant<T1, T2, T3, T4> var_;
public:
    Foo(const T1& t1) : var_(t1) { }
    Foo(const T2& t2) : var_(t2) { }
    Foo(const T3& t3) : var_(t3) { }
    Foo(const T4& t4) : var_(t4) { }

    Foo operator@(const T1& t1) const { return t1 @ boost::get<T1>(var_);}
    Foo operator@(const T2& t2) const { return t2 @ boost::get<T2>(var_);}
    Foo operator@(const T3& t3) const { return t3 @ boost::get<T3>(var_);}
    Foo operator@(const T4& t4) const { return t4 @ boost::get<T4>(var_);}
    Foo operator@(const Foo& foo) const
    {
        switch (foo.which())
        {
         case 0: return *this @ boost::get<T1>(foo.var_);
         case 1: return *this @ boost::get<T2>(foo.var_);
         case 2: return *this @ boost::get<T3>(foo.var_);
         case 3: return *this @ boost::get<T4>(foo.var_);
         }
     }
};

int main()
{
    T1 t11, t12;
    Foo<T1, T2, T3, T4> foo1(t11), foo2(t12);
    Foo<T1, T2, T3, T4> foo = foo1 @ foo2;
    Foo<T1, T2, T3, T4> foo11 = t11 @ foo2;
    Foo<T1, T2, T3, T4> foo12 = foo1 @ t12;
    // assuming we have implemented operator==, I would expect that
    // foo, f11, f12 were all equal here.

    return 0;
}

```

I'm leaving out some type checking and other things for brevity. Hopefully, the point is clear.

Using `std::enable_if_t`, I'm sure we can figure out how to know when `operator@` should be implemented for each `T_i`. However, is there a clever way to use variadic templates to create such a class and have all the operators I want overloaded in the canonical way? I don't specifically need to do this really as there is only one version of such a variadic template that I would use 99.9% of the time, but I think it is an interesting question.