This enables one to write generic code that can be instantiated for both
specific operation classes and the common base class without
specialization. Examples include functions that take/return ops, such
as:
mlir template <typename FnTy> void applyIf(FnTy &&lambda, ...) { for (Operation *op : ...) { auto specific = dyn_cast<function_traits<FnTy>::template arg_t<0>>(op); if (specific) lambda(specific); } }
that would otherwise need to rely on template specialization to support
lambdas that take specific operations and those that take Operation *.