On Tue, Nov 29, 2022 at 10:29 AM Frederick Virchanza Gotham <cauldwell.thomas@gmail.com> wrote:
>
> template<text K, typename T>
> constexpr auto GetRelevantMethodPointer(T const *const p)
> {
> if constexpr ( false == std::is_class_v<T> ) return
> static_cast<void(*)(void)>(nullptr);
> else if constexpr ( std::derived_from<T,std::istream> ) return &T::read;
> else if constexpr ( requires { &T::put; } ) return &T::put;
> else
> {
> return &T::K;
> }
> }
This wasn't a very good example. A better example would be where we
want to find a member of the same name in a different class. See line
#7 in the following:
00: template<typename T>
01: constexpr auto GetRelevantMethodPointer(T const *const p)
02: {
03: if constexpr ( false == std::is_class_v<T> ) return
04: static_cast<void(*)(void)>(nullptr);
05: else if constexpr ( std::derived_from<T,std::istream> )
return &T::read;
06: else if constexpr ( requires { &T::put; } ) return &T::put;
07: else if constexpr ( requires { &SomeOtherClass::K; } ) return
&SomeOtherClass::K;
08: else
09: {
10: return &T::K;
11: }
12: }
This doesn't seem like idiomatic C++ code at all. Generally in C++ you need to stay far away from pointers-to-member, because member functions can be overloaded, or can be function templates, at which point it's impossible to get a member pointer to them at all. Prefer to use C++11 lambdas instead.
template<class T, class Fallback>
auto GetReaderFunction(const T *p, Fallback fallback) {
static_assert(std::is_class_v<T>);
if constexpr (std::derived_from<T, std::istream>) {
return [p](char *s, size_t n) { p->read(s, n); };
} else if constexpr (requires (char *s, size_t n) { p->put(s, n); }) {
return [p](char *s, size_t n) { p->put(s, n); };
} else {
}
}
struct Foo {
void put(auto*, size_t) {}
};
struct Bar {
void baz(size_t) {}
};
int main() {
Foo foo;
Bar bar;
auto one = GetReaderFunction(&std::cin, 0);
auto two = GetReaderFunction(&foo, 0);
auto three = GetReaderFunction(&bar, [&bar](char*, size_t n) { bar.baz(n); });
}
Looking at the call-sites in `main`, you quickly realize that there's no reason to ever pass `fallback` — it will be known statically at compile time whether that parameter is meaningful or not, and if it is meaningful then there's literally no reason to call `GetReaderFunction` in the first place. So this code can continue to be simplified beyond what I've done here.
–Arthur