How can I tell whether I'm forwarding to a copy constructor?

You can use remove_cv_t:

#include <type_traits>

template <typename T, typename... Args>
void CreateTAndDoSomething(Args&&... args) {
  // Special case: if this is copy construction, do something different.
  if constexpr (sizeof...(Args) == 1 && is_same_v<T&, remove_cv_t<Args...> >) { ... }

  // Otherwise do something else.
  ...
}

This covers all "copy constructors" as defined by the standard, not considering possible default arguments (it is hard to determine whether a given function parameter -- for the function that would be invoked given these parameters -- is defaulted or not).

Tags:

C++

Templates