I've been stuck on this for a while and I ran out of ideas, help appreciated!
The following segments are example code, to simplify.
Assume the following:
class Base;
class DerivedA : public Base;
class DerivedB : public Base;
and this:
class Manager {
public:
std::map<std::type_index, Base*> container;
template<typename ...T>
void remove() {
// Iterate through templates somehow and...
container.erase(typeid(T));
}
}
Basically I'm storing, in a container, unique instances of derived classes, by using the std::type_index as a key. Allowing me to do something like:
manager.remove<DerivedA>();
With that said, I'd like to be able to do the same thing, but allow multiple templates directly to remove multiple instances at once, as such:
manager.remove<DerivedA, DerivedB>()
I know it is possible to iterate through variadic templates as described here, but I keep getting compilation errors...
error C2440: 'initializing': cannot convert from 'initializer-list' to 'std::initializer_list'
error C3535: cannot deduce type for 'auto' from 'initializer-list'
...when I try to run this code:
template<typename ...T>
void remove() {
// Iterate through templates somehow and...
auto list = {(container.erase(typeid(T)))... };
}
Any ideas? Thank you very much.
I'm guessing you just ran into an MSVC bug. The compile error:
error C3535: cannot deduce type for 'auto' from 'initializer-list'
isn't valid. C++11 does allow deduction for auto
from a braced-init-list, as long as all the types are the same. In your case, std::map::erase
returns a size_t
, so it should compile. Here is an example with basically your code.
To get around that, you may just be able to explicitly provide the type:
size_t dummy[] = {m.erase(typeid(T))...};
Or, just in case somebody passes in no types, prepend a zero:
size_t dummy[] = {0u, m.erase(typeid(T))...};
That way, the array will always have at least one element. The more typical usage, which Kerrek suggested in his comment, would be the following:
int dummy[] = {0, (void(m.erase(typeid(T)), 0)... };
That will work regardless of the expression that you will replace m.erase(...)
with, since the value of (..., 0)
is 0
. The void
is there to avoid issues with overloading operator,
.