You cannot automatically deduce Base
. Furthermore there isn't even an implicit conversion of Derived1*
or Derived2*
to Base*
, since you're using a private base class.
I'm assuming you actually wanted public base classes in the following code
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
.
You cannot deduce the common base class of both Derived1
and Derived2
, so the type actually needs to be mentioned, if you want to use anything that's iterable, you need to manually specify the type.
However you could create a template function with a parameter pack to either execute a functor for every parameter passed or to create something that is an iterable that returns references to Base
when dereferencing the iterator.
In the following I show both options, but for simplicity's sake I go with an std::array
of std::reference_wrapper<Base>
instead of implementing custom collection that has an iterator returning references to Base
.
template<class F, class...Args>
void ForEach(F&& f, Args&&...args)
{
((f(std::forward<Args>(args))), ...);
}
void printType(Derived1 const&)
{
std::cout << "Derived1\n";
}
void printType(Derived2 const&)
{
std::cout << "Derived2\n";
}
void printType(Base const&)
{
std::cout << "Base\n";
}
template<class T, class ...Args>
std::array<std::reference_wrapper<T>, sizeof...(Args)> AsIterable(Args& ...args)
{
return {args...};
}
int main()
{
Derived1 var1, var2;
Derived2 var3, var4;
std::cout << "generic lambda:\n";
ForEach([](auto& x)
{
printType(x);
}, var1, var2, var3, var4);
std::cout << "lambda with typed parameter:\n";
ForEach([](Base& x)
{
printType(x);
}, var1, var2, var3, var4);
std::cout << "range-based for loop with reference wrapper array:\n";
for (auto& var : AsIterable<Base>(var1, var2, var3, var4))
{
// note: var has type std::reference_wrapper<Base>&, not Base& as mentioned above
printType(var);
}
std::cout << "pointer values(main):\n"
<< &var1 << '\n'
<< &var2 << '\n'
<< &var3 << '\n'
<< &var4 << '\n'
;
std::cout << "pointer values(lambda):\n";
ForEach([](Base& x)
{
std::cout << &x << '\n';
}, var1, var2, var3, var4);
std::cout << "pointer values(range-based for):\n";
for (auto& var : AsIterable<Base>(var1, var2, var3, var4))
{
std::cout << &var.get() << '\n';
}
}