I have a group of classes and inside each one is defined a nested class always with the same name.
class A {
public:
class Common {};
...
};
class B {
public:
class Common {};
...
};
I am trying to write a template function like this (NOT compiling code):
template<typename T, typename... ARGS>
void foo(T::Common tc, ARGS... args) {
T t(tc, args...);
// do stuff
}
And I would like to use it as follow:
{
...
A::Common ac();
foo(ac, 42, "Hello");
....
}
How could I extract the outer class type from the type on the inner class instance passed to the function? Maybe with <traits>
, but I am very newbie about it...
If you want your inner class to access outer class instance variables then in the constructor for the inner class, include an argument that is a reference to the outer class instance. The outer class invokes the inner class constructor passing this as that argument.
The inner class can access any non-static member that has been declared in the outer class. Scope of a nested class is limited by the scope of its (outer) enclosing class. If nothing is specified, the nested class is private (default). Any class can be inherited into another class in C# (including a nested class).
Java inner class is associated with the object of the class and they can access all the variables and methods of the outer class. Since inner classes are associated with the instance, we can't have any static variables in them.
Bookmark this question. Show activity on this post. private This is the default, and means that the method or variable is accessible only within the Apex class in which it is defined.
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With