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).