The using of libsolv to manage package dependencies is only the first part of packaging work. The second one, much more involving, is to actually design the packages (what exactly they contain) and their dependencies.
Again, I will speak about how this problem is handled with deb/dpkg/apt. When more than one implementation of some library exist in repository, they both provide the same impementing virtual package. When some software needs the functionality regardless of the concrete implementing, it is made dependent on the virtual package. One implementing package is marked as the default. So when no implementation is installed at all this real package is installed.
So, consider libjpeg virtual package (contains no files, only dependencies) and 2 its implementing packages jpeg2000 and jpeg-turbo, both provide libjpeg. One of them is default, say jpeg-turbo.
- When someone installs a package that
requireslibjpeg, the system checks iflibjpegis installed. This only happens when either of its implementations is installed. When none is, the defaultjpeg-turbois installed as well aslibjpegwhich itprovides. - When now someone installs some other package that
requiresconcretejpeg2000package, this one is installed, alsoprovidinglibjpeg. In this casejpeg2000is installed as required butjpeg-turbois installed as dependency oflibjpegand is uninstalled. - In case there are 2 packages, one depends on
jpeg2000and another onjpeg-turbo, no conflict exists, and provision of 2 implementations oflibjpegis irrelevant. - In case there are 3 packages, one depends on
jpeg2000, one onjpeg-turboand one onelibjpeg, the latter can link against whatever finds first or against the default implementationjpeg-turbo(because bothprovidethe same symbols, it is expected to be possible to link with either).

