There are a number of toolchain packages, including the gcc suite, python and the llvm suite in Debian/Ubuntu for which multiple versions are packaged at once under different package names.
This is done for various reasons including.
- It provides an "escape hatch" of temporarily reverting builds of a package to a previous version if the new version causes build failures. This sort of thing is particularly helpful for compilers that need themselves to build.
- It allows new versions to be tested and/or used by early adopter packages before switching the default for the whole distribution.
- It allows different language frontends and/or different architectures to switch versions at different times.
There is a "defaults" source package (gcc-defaults for gcc) which builds packages that do not have the version number as part of their name. These packages are used by the distribution to set the default version of the tool.
So the gcc-7 package contains gcc version 7.x. The gcc package depends on and contains a symlink to the major version of gcc that is the "default" for that particular release.
gcc-<version>-base contains a few files that are shared by all packages built from the gcc source package. In particular this includes libstdc++6.
libstdc++6 does not use the "defaults" system and comes from the most recent gcc-x source package in the release. Even if that release of gcc has not been made the default.
It looks like 18.04 has gcc 7 as the default gcc version but has libstdc++ from gcc-8, hence why both gcc-7-base and gcc-8-base are installed.
Unfortunately 18.04 has now been removed from packages.ubuntu.com, but the wayback machine has copies of the pages in question showing that the default gcc is version 7 but libstdc++6 comes from the gcc-8 source package.
http://web.archive.org/web/20230208173902/https://packages.ubuntu.com/bionic/gcc
http://web.archive.org/web/20220809174431/https://packages.ubuntu.com/bionic/libstdc%2B%2B6