0

Suppose I have a bar and a foo structures:

struct bar {
    void bar_function() { }
};

struct foo {
    bar* bar_ptr;

    void foo_function() { }
};

Now, I'd like to call bar_function() on each of foo's bar_ptrs from an std::vector of foos:

std::vector<foo> fooVec;

ranges::for_each(
        fooVec,
        &bar::bar_function,
        &foo::bar_ptr
);

This uses range-v3's projections - for each foo, we take out bar_ptr from it and then we call bar_function on each of them.

I would assume that the above will work - we can, after all, std::invoke a &bar::bar_function with a pointer to a bar (which we do have - the bar_ptr). For the record I know that range-v3 uses std::invoke magic to always do the right thing, so it surprises me that this fails with the following error:

error: no match for call to '(const ranges::for_each_fn) (std::vector<foo>&, void (bar::*)(), bar* foo::*)'
[...]
error: no class template named 'apply' in 'struct ranges::detail::enable_if<false>'
73 |         using enable_if_t = typename enable_if<B>::template apply<T>;
   |               ^~~~~~~~~~~
[...]

I'm not quite sure which part of the error is relevant here - I know that this fails the SFINAE tests, but I do not know why. Is there a reason why the above should fail or is it a bug?


Note that, if we replace &bar::bar_function with [](auto bar_ptr) { bar_ptr->bar_function(); }, the code happily compiles, which is weird, because, due to std::invoke's nature (to "always do the right thing"), I fail to see the difference between those two:

std::invoke(&bar::bar_function, bar_ptr); // 1

std::invoke([](auto bar_ptr_arg) {        // 2
    bar_ptr_arg->bar_function();
}, bar_ptr);
Mohsen Alyafei
  • 4,765
  • 3
  • 30
  • 42
Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • Seems [fine](https://godbolt.org/z/7TGxGe). What compiler are you using? – cigien Jul 17 '20 at 23:29
  • @cigien [Stephan's lastest MinGW](https://nuwen.net/mingw.html) (GCC 9.2.0) and Range-v3 from Eric Niebler's GitHub from exactly one month ago. – Fureeish Jul 17 '20 at 23:32
  • Probably a bug. Works on regular [gcc9.2](https://godbolt.org/z/3q5ob5) as well. – cigien Jul 17 '20 at 23:34
  • @cigien interesting. Can you confirm which range-v3 version godbolt uses? Not sure whether that's the library or the compiler that's behind the problem at my end. – Fureeish Jul 17 '20 at 23:36
  • 1
    You can try it with various versions on godbolt. This works on trunk. – cigien Jul 17 '20 at 23:37

0 Answers0