With lsp you don't need tags. You essentially have a lsp server like clangd [0] running in the background for finding references, definitions, code completion etc.
With the latest release 29.1, emacs comes with an in-built lsp client - eglot[1]. So you need to (a) Set up clangd or some other lsp server for c++. Make sure it's accessible from emacs (use something like exec-path-from-shell to get your shell paths into emacs) (b) Set up your project for clangd - this involves generating a compile_commands.json which basically lists the full compilation invocation of each and every file in your project. CMake has options to do that and likely many other build tools or maybe use something like bear[2]. (c) Enable eglot (install the package if needed on older versions of emacs) and configure appropriately.
I also use projectile for project mgmt though emacs now has something in built for that too.
With the latest release 29.1, emacs comes with an in-built lsp client - eglot[1]. So you need to (a) Set up clangd or some other lsp server for c++. Make sure it's accessible from emacs (use something like exec-path-from-shell to get your shell paths into emacs) (b) Set up your project for clangd - this involves generating a compile_commands.json which basically lists the full compilation invocation of each and every file in your project. CMake has options to do that and likely many other build tools or maybe use something like bear[2]. (c) Enable eglot (install the package if needed on older versions of emacs) and configure appropriately.
I also use projectile for project mgmt though emacs now has something in built for that too.
I can post my configs if that helps.
[0] https://clangd.llvm.org/ [1] https://github.com/joaotavora/eglot [2] https://github.com/rizsotto/Bear