In your following function template:
template<typename T, typename... ARGS>
void foo(T::Common tc, ARGS... args);
T
is in a non-deducible context. Therefore, doing:
foo(ac, 42, "Hello");
won't compile, because T
can't be deduced from the function call arguments. You would need to explicitly pass A
as an argument to the T
template parameter:
foo<A>(ac, 42, "Hello");
However, note that T::Common
will actually have to be preceded by the keyword typename
, since Common
is a type-dependent name:
template<typename T, typename... ARGS>
void foo(typename T::Common tc, ARGS... args);
Extracting the outer class type without giving up implicit type deduction
You could declare an outer_class_of<>
class template for extracting the outer class. This template would be parameterized by the inner class type:
// primary template
template<typename>
struct outer_class_of;
Then, specialize this template for both A::Common
and B:Common
:
// specialization for A::Common
template<>
struct outer_class_of<A::Common> {
using type = A; // outer class of A::Common
};
// specialization for B::Common
template<>
struct outer_class_of<B::Common> {
using type = B; // outer class of B::Common
};
You can declare then an alias template for achieving C++14-like _t
type traits:
template<typename T>
using outer_class_of_t = typename outer_class_of<T>::type;
This way, outer_class_of_t<A::Common>
corresponds to A
and outer_class_of_t<B::Common>
to B
.
Finally, you need to change your foo()
function template definition to:
template<typename TCommon, typename... ARGS>
void foo(TCommon tc, ARGS... args) {
outer_class_of_t<TCommon> t(tc, args...);
}
When calling foo()
with a A::Common
or a B::Common
object as function argument, TCommon
will be deduced to A::Common
or B::Common
, respectively. outer_class_of<>
is then applied on TCommon
to obtain the type of the outer class.
Also, be ware of C++'s most vexing parse in:
A::Common ac();
What you want is actually:
A::Common ac{};
Otherwise, in the call to foo()
, TCommon
will be deduced to A::Common(*)()
(i.e.: a pointer to function) instead of A::Common
, since the former is declaring a function that takes no parameters and returns an A::Common
object, whereas the latter is actually declaring an A::Common
object.