For something like a texture there may actually be a point to copying it, but for a shader object much less so (in my experience). Even for objects where copying makes sense, you don't want to do it very often so you want to make it very explicit.
Either you use your wrapper class by-value (so it is something like a handle to your OpenGL entity) and it uses reference counting internally, or you consider your wrapper class instance to own the OpenGL entity and you use reference counting on your wrapper class itself (using std::shared_ptr for example).
In the latter case you could implement a copy-constructor only on those entities for which it makes sense. However, in order to avoid unintentional use I normally resort to a private constructor and a public static factory function on the entity that returns a new instance as a smart pointer, so it is not mistakenly used by-value. In that case it also makes more sense to have an explicit "Copy/Clone" member function (easier to use and it allows for polymorphism).
In the former case the copy-constructor only increments the reference count, so you will need to add some explicit member for copying where appropriate anyway.
I usually go with the latter option by the way... I'm used to passing resource-intensive objects around by smart pointers and I don't see much point in reimplementing their functionality in custom handles.