0

I know there is a similar problem here

My question is slightly different from that, what does it mean When c::* appears in the template parameter,

template <typename C>
static yes& f(typename std::enable_if<
    std::is_same<decltype(static_cast<typename C::const_iterator(C::*)() const>(&C::begin)),
    typename C::const_iterator(C::*)() const>::value>::type*);

from here

Can someone explain what this piece of code means,especially this one

typename C::const_iterator(C::*)()

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
Kargath
  • 450
  • 5
  • 15

2 Answers2

0

what does it mean When c::* appears

Outside of context, it is part of syntax for a pointer to member of c.

When put in context: C::const_iterator(C::*)() const type is pointer to const qualified member function of C that returns C::const_iterator and has empty parameter list.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

IMHO that's awfully constructed statement over there, it's unreadable. But it can be "disassembled" hierarchically:

template <typename C>
static yes & f (
    typename std::enable_if<
        std::is_same<
            decltype(
                static_cast<
                     typename C::const_iterator(C::*)() const
                >(&C::begin)
            ),
            typename C::const_iterator(C::*)() const
        >::value
    >::type *
);

It declares a template with class parameter C of function f that returns yes&.

The function instance will have a parameter of type void* if typename C::const_iterator(C::*)() const and the type of result of cast of &C::begin to C::const_iterator(C::*)() const are same, otherwise the template won't produce legal instance due to SFINAE, because std::enable_if<>::type won't be declared (std::enable_if<expr>::type defaults to void if expr is true)

typename C::const_iterator(C::*)() const is a pointer to member of class C with signature similar to C::const_iterator name () const, i.e. it returns C::const_iterator, takes no parameters, and is a const member. In standard prior to C++20 you have to use typename if declaration depends on template parameter, it seems that requirement is proposed to be lifted in latest standard.

static_cast<typename C::const_iterator(C::*)() const> is there likely to protect from case when C::begin is an overloaded function member, it would choose the proper overload.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • Thank you, I am used to Range-based for loop, I almost forget that begin is a function>_ – Kargath Dec 20 '20 at 13:03
  • @鱼门国主 ranged loops are usable only if you don't invalidate iterators of collection. E.g. if you try to remove element, you can't replace current iterator value (and now invalid after element it was pointing to was removed) with new one returned. – Swift - Friday Pie Dec 20 '20 at 13:05