So for the purpose of example let's say I have 3 simple struct
s, the second of which doesn't contain a bar
method:
struct one {
void foo(const int);
void bar();
};
struct two {
void foo(const int);
};
struct three {
void foo(const int);
void bar();
};
Then I have a struct
which will manage objects of these types:
struct owner {
map<int, one> ones;
map<int, two> twos;
map<int, three> threes;
template <typename T, typename Func>
void callFunc(T& param, const Func& func) {
func(param);
}
template <typename T>
void findObject(int key, const T& func) {
if(ones.count(key) != 0U) {
callFunc(ones[key], func);
} else if(twos.count(key) != 0U) {
callFunc(twos[key], func);
} else {
callFunc(threes[key], func);
}
}
void foo(const int key, const int param) { findObject(key, [&](auto& value) { value.foo(param); } ); }
void bar(const int key) { findObject(key, [&](auto& value) { value.bar(); } ); }
};
When I try to compile this I get:
error:
struct two
has no member namedbar
Is there a way that I can work around this?
First, the utilities. One is our favorite
overload
that shows off three C++17 features, and overloads theoperator()
of several function objects, all in two lines.Then an accepts-everything fallback tag type:
Now to the call itself. We make the original generic lambda SFINAE-friendly by putting the
value.bar()
call into the trailing return type, then overload it with a fallback overload that has undefined behavior if actually invoked (since OP "omit[ted] any explicit definition of behavior"):