Title
Deduced return types vs member types
Status
drafting
Section
11.4.9.3 [class.static.data]
Submitter
John Spicer

Created on 2017-01-29.00:00:00 last changed 41 months ago

Messages

Date: 2018-06-15.00:00:00

Notes from the June, 2018 meeting:

The consensus of CWG was to treat templates and classes the same by "instantiating" delayed-parse regions when they are needed instead of at the end of the class.

See also issue 1890.

Date: 2018-03-15.00:00:00

Notes from the March, 2018 meeting:

It was proposed that one direction might be to disallow instantiating member functions while the containing class template is being instantiated. However, overnight implementation experience indicated that this approach breaks seemingly-innocuous and currently-accepted code like:

  template <class T> struct A {
    static constexpr int num() { return 42; }
    int ar[num()];
  };
  A<int> a;

There was divergence of opinion regarding whether the current rules describe the current behavior for the two original examples or whether additional explicit rules are needed to clarify the difference in behavior between template and non-template examples, as well as whether there should be a difference at all..

Date: 2017-01-29.00:00:00

It is not clear how an example like the following should be treated:

  template <class ...> struct partition_indices {
    static auto compute_right () {}
    static constexpr auto right = compute_right;
  };
  auto foo () -> partition_indices<>;
  void f() {
    foo();
  };

The initialization of right is in a context that must be done during the initial parse of the class, but the function body of compute_right is not supposed to be evaluated until the class is complete. Current implementations appear to accept the template case but not the equivalent non-template case. It's not clear why those cases should be treated differently.

If you change the example to include a forward dependency in the body of compute_right, e.g.,

  template <int> struct X {};
  template <class T> struct partition_indices {
    static auto compute_right () { return X<I>(); }
    static constexpr auto right = compute_right;
    static constexpr int I = sizeof(T);
  };

  auto foo () -> partition_indices<int>;

  void f() {
    foo();
  };

current implementations reject the code, but it's not clear that there is a rationale for the different behavior.

History
Date User Action Args
2020-12-15 00:00:00adminsetmessages: + msg6242
2020-12-15 00:00:00adminsetstatus: open -> drafting
2018-04-11 00:00:00adminsetmessages: + msg6208
2017-01-29 00:00:00admincreate