In fact, I saw some designers would like the similar functionality and tried using parameterized class and static functions to achieve their need. Why static function? Because when the function is not static, you have to new a class object and invoke method call, which is not actually synthesizable.
In fact, this doable workaround is actually a hacky way. Theoretically, this coding style should be able to synthesis, but it could lead to serious issues. If the function is not a pure function, it can access other static members, but in hardware, which module should hold the static member? Is there possible out-of-module reference to the static member? Because the static variables can be read/write by all non-static methods, it is possible that the value is modified by other non-synthesizable code. If the static member is duplicated to each module which invokes the function call, then the outcome is not as expected as simulation results.class my_class #(parameter W = 32); static function bit word_or(input [W-1:0] in); return |in; endfunction endclass
Practically SystemVerilog does support another usage, which is let expression. let expression supports typeless arguments, so the type and width of its arguments are determined in the expression reference.
However, because it is an expression, you cannot write sequence block statements like a function does.package my_package; let word_or(in) = !in; endpackage logic [15:0] abc; assign result = my_package::word_or(abc);
My conclusion is using static parameterized function in parameterized class in not a recommended approach and not has good interoperability in tools.