I have a template action
method that accepts any kind of STL container C
. However the contained items (C::value_type
) must be either ClassA
or ClassB
. So far so good:
struct Whatever {
template<typename C>
void action(const C& c) {
static_assert(std::is_same<typename C::value_type, ClassA>::value ||
std::is_same<typename C::value_type, ClassB>::value,
"Wrong C::value_type");
// do something with c
}
};
// Usage:
Whatever w;
w.action(std::vector<ClassA>{1, 2, 3});
w.action(std::unordered_set<ClassB>{1, 2, 3});
Note: the enclosing class is not a template, the only template is this very action
method.
Now, depending on C::value_type
, I want to specialize the behaviour of the method. You guessed it, that's where my brain starts melting.
I believe SFINAE is the way to go but obviously I'm too rusty to make it work properly: after several hours, tons of helper structs
and way too much coffee for my own health, the compiler just keeps yelling the usual 500+ template errors at me. No point in copying either my helper structs
or the errors here, that's pretty much useless junk.
However, I have to admit I didn't really keep in touch with all the C++ template (r)evolutions (or even use SFINAE, at that) since a good decade so it's no wonder I'm failing so hard.
I strongly suspect C++11 now has easy, ready-to-use SFINAE-like tools to achieve what I want but I don't even know where to begin searching in the documentation. Search engines didn't help either, there's just too much new information at once for me to be able to understand what is/isn't relevant to my problem.
Since I'm at a total loss, I'll just take baby steps and ask SO... My question is two-fold:
- How can I specialize the behaviour of the method depending on the actual type of
C::value_type
using modern C++11 template tools?
- Optionally, is there a standard way to check if
C
actually is a container?
Thanks for your attention.