A utility to swap two files
file1_path == file2_path surely tells that paths refer to the same file. However, even if file1_path != file2_path they still may refer to the same file.

file1_exists = std::filesystem::exists(file1_path); introduces a TOC-TOU race condition. The file may exist at the time of test, yet disappear by the time of use. See the next bullet.

std::filesystem::rename may fail. You call it tree times. If the second, or third call fails (with an exception!), the filesystem ends up not exactly in a state one would expect. Use a noexcept overload, test the error_code after each call, and roll back all actions prior to failure. That would also automagically take care of the nonexistent paths.

Do not assert. It is only good to catch bugs, not the runtime problems. In the production code (compiled with -DNDEBUG) it does nothing, and your program wouldn't detect an mkstemp failure.

The program silently does nothing if called with, say, 4 arguments. It also takes so much effort if called with 2 arguments. Calling print_help() any time argc != 3 is much more straightforward.