--- Quote Start ---
Unconstrained 2d arrays are part of the VHDL 2008 spec, and modelsim 10+ should handle them fine. VHDL 2008 also allows you to declare types, functions, procedures etc in the generic region, but I doubt Quartus will bother supporting this any time soon.
--- Quote End ---
I'm not so sure about ModelSim either, e.g. it doesn't handle the if generate-else generate construct. It does handle std_logic_2D flawlessly.
--- Quote Start ---
So you will need a package (which is usually the most sensible thing anyway). Any reason you dont want a package?
--- Quote End ---
Packages where you constrain otherwise 'generic' objects are a hassle too as you have to do that on a project basis, which is OK for the project specific types but not nice if you then want to call a generic module. E.g you could have a n x n kernel with a std_logic_2D output which you then feed into a generic summation module. If you use a package-constrained type you have to write a wrapper around the code (not sure this always works) or even worse change the source code on a per project basis replicating copies everywhere.
--- Quote Start ---
I would personally avoid std_logic_2d type because of what josyb has said - it can cause a lot of hassle and you need conversion functions to break your arrays out of there.
--- Quote End ---
I have written a lot of std_logic_2D functions taking the hassle out of std_logic_2D.
If you look at VHDL from a more purist view, the 2D-array is, IMHO, a more 'natural' object then what is commonly called a 1Dx1D type. I lately experimented with 3D and 4D objects which both ModelSim and Quartus handle fine.
Altera uses the std_logic_2D originated to represent the double array in AHDL: arr[][] as used in e.g. lpm_mux.