Yes, this should create a different instance of class template. They should only differ in the size of the array passed by reference and if they array isn't really used any further as array, the generated code should be identical. As far as I know, VC++ folds identical code. If the type is propagated a lot, it may yield code bloat, however.
One way to prevent the code bloat is to conditionally decay types and forward to another template doing the actual work. I think this should do the trick:
template <typename... Args>
void my_real_log_function(Args&&... args) {
// real implementation goes here
}
template <typename T>
struct decay_array {
typedef typename std::condition<
std::is_array<typename std::remove_reference<T>::type>::value,
typename std::decay<T>::type,
T>::type type;
};
template <typename... Args>
void my_log_function(Args&&... args) {
my_real_log_function(std::forward<typename std::decay_array<Args>::type>(args)...);
}
The original version just using typename std::decay<T>::type doesn't work because it would turn references to non-arrays into values which isn't intended.
my_log_function(+"1")deducesArgs...to beconst char*(using unary+); similarly you could dispatch the work to another template, passing decayed arguments (with the intent of eliminating / inlining the originally invoked function)