This question is basically an aftermath of this answer I gave. I just realized that the wording in the standard seems to omit a few cases. Consider this piece of code:
#include <iostream>
#include <functional>
struct foo
{
void f(int v) { std::cout << v << std::endl; }
};
struct bar : foo {};
int main()
{
bar obj;
std::bind(&foo::f, obj, 1)();
}
The standard describes in 20.8.9.1.2 the effect of std::bind
and what happens when it is invoked. It forwards to 20.8.2, the relevant part is:
20.8.2 Requirements [func.require]
1 Define INVOKE
(f, t1, t2, ..., tN)
as follows:—
(t1.*f)(t2, ..., tN)
whenf
is a pointer to a member function of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;—
((*t1).*f)(t2, ..., tN)
whenf
is a pointer to a member function of a classT
andt1
is not one of the types described in the previous item;—
t1.*f
whenN == 1
andf
is a pointer to member data of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;—
(*t1).*f
whenN == 1
andf
is a pointer to member data of a classT
andt1
is not one of the types described in the previous item;—
f(t1, t2, ..., tN)
in all other cases.
Reading this, it seems to allow three cases for the first list item:
t1
is an object of typeT
- or a reference to an object of type
T
- or a reference to an object of a type derived from
T
but in my example, it is neither. It's a type derived from T
, but without a reference. Shouldn't the above listed cases be:
t1
is an object of typeT
- or an object of a type derived from
T
- or a reference to an object of type
T
- or a reference to an object of a type derived from
T
Of course, the same applies to the third list item in 20.8.2.
Question 1: As both GCC and Clang accept my code, I wonder if this is a defect report against the standard or if I'm just reading it wrong.
Question 2: With multiple/virtual inheritance, even if a type is derived from T
, it might not simply be possible to call (t1.*f)(...)
on it, right? Is that also something I should be concerned about or does the standard define "derived from" clearly in the given context?