Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[basic.life] Calling an explicit object member function with a function pointer and an out-of-lifetime object #671

Open
frederick-vs-ja opened this issue Feb 6, 2025 · 1 comment

Comments

@frederick-vs-ja
Copy link

Full name of submitter (unless configured in github; will be published with the issue): Jiang An, Li Qiuyi

Reference (section label): [basic.life]

Link to reflector thread (if any):

https://lists.isocpp.org/std-proposals/2025/01/11954.php

Issue description:

It's not very clear how to apply [basic.life] p7.2 and [basic.life] p8.2 when the non-static member function is an explicit object member function whose object parameter type is weird, and the function is called via a function pointer.

Consider the following example (Godbolt link; note that constructing a T from a non-living S can be well-defined per CWG453).

struct S;

struct T {
  constexpr T(const S&) {} // The parameter can references a non-living object as clarified in CWG453.
};

struct S {
  constexpr void fun(this T) {}
};

static_assert([]{
  constexpr auto funptr = &S::fun;
  union U { S s; } u; // u.s is inactive.
  {
    u.s.fun();      // #1
  }
  {
    funptr(u.s);    // #2
  }
  {
    funptr(T{u.s}); // #3
  }
  return true;
}());

It seems that #1, #2, and #3 perform equivalent operations. However,

  • [basic.life] p8.2 perhaps indicates that #1 is UB (although implementations accept it in constant evaluation);
  • #2 has no formally object argument, and it's unclear whether u.s can be treated as the object argument;
  • there doesn't seem any object argument (of type S) in #3, and #3 seems well-defined.

Even when the object parameter type is conventional, e.g. in (the simplified version of) the example in the original thread:

struct A {
  A(){} // not trivial
  ~A(){}
  void f2(this const A&);
};

int main() {
  A a{};
  a.~A();
  a.f2(); // UB or not?
  auto p = &A::f2;
  p(a); // UB or not?
  new(std::addressof(a))A{}; // OK
}

It doesn't seem very clear that p(a) raises UB.

Suggested resolution:

@frederick-vs-ja frederick-vs-ja changed the title [basic.life] Calling an explicit object member functions with a function pointer and an out-of-lifetime object [basic.life] Calling an explicit object member function with a function pointer and an out-of-lifetime object Feb 6, 2025
@t3nsor
Copy link

t3nsor commented Feb 14, 2025

I think we should treat explicit object member functions like static member functions as much as possible:

  • [basic.life]/8.2 should be restricted to implicit object member functions
  • [class.cdtor]/1 should be restricted to non-static data members and implicit object member functions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants