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';
}
}