Movatterモバイル変換


[0]ホーム

URL:


This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-12-20


1351. Problems with implicitly-declaredexception-specifications

Section:14.5  [except.spec]    Status:CD4    Submitter:Richard Smith    Date:2011-08-16

[Moved to DR at the November, 2014 meeting.]

The determination of theexception-specification for animplicitly-declared special member function, as described in14.5 [except.spec] paragraph 14, does not take into account thefact that nonstatic data member initializers and default arguments indefault constructors can containthrow-expressions, which arenot part of theexception-specification of any function that is“directly invoked” by the implicit definition. Also, thereference to “directly invoked” functions is notrestricted to potentially-evaluated expressions, thus possiblyincluding irrelevantexception-specifications.

Additional note (August, 2012):

The direction established by CWG for resolving this issue was toconsider functions called from default arguments and non-static datamember initializers in determining theexception-specification.This leads to a problem with ordering: because non-static data memberinitializers can refer to members declared later, their effect cannotbe known until the end of the class. However, a non-static datamember initializer could possibly refer to an implicitly-declaredconstructor, either its own or that of an enclosing class.

Proposed resolution (October, 2012) [SUPERSEDED]:

  1. Add the following two new paragraphs and make the indicatedchanges to 14.5 [except.spec] paragraph 14:

  2. Aset of potential exceptions may contain types and thespecial value “any.” Theset of potential exceptions ofan expression is the union of all sets of potential exceptions ofeach potentially-evaluated subexpressione:

    Theset of potential exceptions of a functionf of some classX, wheref is an inheritingconstructor or an implicitly-declared special member function, isdefined as follows:

    An inheriting constructor (_N4527_.12.9 [class.inhctor]) and animplicitly declaredimplicitly-declared specialmember function (11.4.4 [special])have anare considered to have an implicitexception-specification.Iff is an inheritingconstructor or an implicitly declared default constructor, copyconstructor, move constructor, destructor, copy assignment operator,or move assignment operator, its implicitexception-specification specifies thetype-idTif and only ifT is allowed by theexception-specification of a function directly invoked byf's implicit definition;f allows all exceptions ifany function it directly invokes allows all exceptions, andfhas theexception-specificationnoexcept(true) ifevery function it directly invokes allows no exceptions.The implicitexception-specification isnoexcept(false) if the set of potential exceptions of thefunction contains “any;” otherwise, if that setcontains at least one type, the implicit exception-specificationspecifies each type T contained in the set; otherwise, the implicitexception-specification isnoexcept(true).[Note: An instantiation of an inheriting constructor templatehas an impliedexception-specification as if it were anon-template inheriting constructor. —end note][Example:

      struct A {    A();    A(const A&) throw();    A(A&&) throw();    ~A() throw(X);  };  struct B {    B() throw();    B(const B&) throw();    B(B&&, int = (throw Y(), 0)) throw(Y)noexcept;    ~B() throw(Y);  };  struct D : public A, public B {      // Implicit declaration of D::D();      // Implicit declaration of D::D(const D&) noexcept(true);      // Implicit declaration of D::D(D&&) throw(Y);      // Implicit declaration of D::~D() throw(X, Y);  };

    Furthermore, if...

  3. Change 7.6.2.7 [expr.unary.noexcept] paragraph 3 as follows:

  4. The result of the noexcept operator isfalse ifin apotentially-evaluated context theset of potentialexceptions of the expression(14.5 [except.spec])would containcontains“any” or at least one type andtrueotherwise.

    Otherwise, the result istrue.

(This resolution also resolves issues1356 and1465.)

Additional note (October, 2012):

The preceding wording has been modified from the version thatwas reviewed following the October, 2012 meeting and thus has beenreturned to "review" status.

Additional note (March, 2013):

It has been suggested that it might be more consistent withother parts of the language, and particularly in view of thedeprecation ofdynamic-exception-specifications, if apotentially-throwing non-static data member initializer simply madean implicit constructornoexcept(false) instead ofgiving it a set of potential exception types.

Additional note, April, 2013:

One problem with the approach suggested in the preceding notewould be something like the following example:

  struct S {    virtual ~S() throw(int);  };  struct D: S { };

This approach would make the example ill-formed, becausethe derived class destructor would be declared to throwtypes not permitted by the base classdestructor'sexception-specification. A furtherelaboration on the suggestion above that would not have thisobjection would be to define alldynamic-exception-specifications as simply equivalent tonoexcept(false).

(See alsoissue 1639.)

Additional note, April, 2013:

The version of this resolution approved in Bristolassumed the underlying text of the C++11 IS; however, thewording of 14.5 [except.spec] paragraph 14 has beenchanged by previous resolutions, so this and the relatedissues are being returned to "review" status.

Proposed resolution, February, 2014 [SUPERSEDED]:

  1. Change 14.5 [except.spec] paragraph 5 as follows:

  2. If a virtual function has anexception-specification,all declarations, including the definition, of any functionthat overrides that virtual function in any derived classshall only allow exceptions that are allowed bytheexception-specification of the base class virtualfunction, unless the overriding function is defined asdeleted. [Example:...
  3. Add the following two new paragraphs and change14.5 [except.spec] paragraph 14 as indicated:

  4. Aset of potential exceptions may containtypes and the special value “any”. Theset ofpotential exceptions of an expression is the union ofall sets of potential exceptions of eachpotentially-evaluated subexpressione:

    Theset of potential exceptions of animplicitly-declared special member functionfof some classX is defined as follows:

    An inheriting constructor (_N4527_.12.9 [class.inhctor]) andan implicitly-declared special member function(11.4.4 [special])haveareconsidered to haveanimplicitexception-specification.Iffis an inheriting constructor or an implicitly declareddefault constructor, copy constructor, move constructor,destructor, copy assignment operator, or move assignmentoperator, its implicitexception-specificationspecifies thetype-idT if and onlyifT is allowed bytheexception-specification of a function directlyinvoked byf's implicit definition;fallows all exceptions if any function it directly invokesallows all exceptions, andf hastheexception-specificationnoexcept(true) if every function it directlyinvokes allows no exceptions. [Note: It followsthatf has theexception-specificationnoexcept(true) if it invokes no otherfunctions. —end note] [Note: Aninstantiation of an inheriting constructor template has animpliedexception-specification as if it were anon-template inheriting constructor. —end note]The implicitexception-specification isnoexcept(false) if the set of potential exceptions of thespecial member function contains “any”; otherwise, if thatset contains at least one type, theimplicitexception-specification specifies each typeT contained in the set; otherwise, theimplicitexception-specificationisnoexcept(true). [Example:

      struct A {    A();    A(const A&) throw();    A(A&&) throw();    ~A() throw(X);  };  struct B {    B() throw();    B(const B&)= default; // Declaration ofB::B(const B&) noexcept(true)throw();    B(B&&, int = (throw Y(), 0))throw(Y)noexcept;    ~B() throw(Y);  };  struct D : public A, public B {      // Implicit declaration of D::D();      // Implicit declaration of D::D(const D&) noexcept(true);      // Implicit declaration of D::D(D&&) throw(Y);      // Implicit declaration of D::~D() throw(X, Y);  };

    Furthermore...

  5. Change 7.6.2.7 [expr.unary.noexcept]paragraph 3 as follows:

  6. The result of thenoexcept operatorisfalsetrueifin a potentially-evaluated contexttheset of potential exceptions oftheexpression(14.5 [except.spec])wouldcontainis empty, andfalseotherwise.

    Otherwise, the result istrue.

    (This resolution also resolves issues1356,1465, and1639.)

Additional note, May, 2014:

The current version of the proposed resolution only defines the set ofpotential exceptions for special member functions; since an inheritingconstructor is not a special member function, theexception-specification for an inheriting constructor isno longer specified.

In addition, the structure of the specification of the set ofpotential exceptions of an expression is unclear. If the bulletedlist is intended to be the definition of general statement (“unionof all sets of potential exceptions...”), it's incomplete becauseit doesn't consider exceptions thrown by the evaluation of functionarguments in a call, just the exceptions thrown by the function itself;if it's intended to be a list of exceptions to the general rule, therule about core constant expressions doesn't exclude unselectedsubexpressions that might throw, so those exceptions are incorrectincluded in the union.

The issue has been returned to "review"status to allow discussion of these points.

See also the discussion in messages25290 through25293.

Proposed resolution (June, 2014):

  1. Change 14.5 [except.spec] paragraph 5 as follows:
  2. If a virtual function has anexception-specification, alldeclarations, including the definition, of any function thatoverrides that virtual function in any derived class shall onlyallow exceptions that are allowed bytheexception-specification of the base class virtualfunction, unless the overriding function is defined asdeleted. [Example:...
  3. Add the following new paragraphs following 14.5 [except.spec] paragraph 13:

  4. Anexception-specification is not considered part of afunction's type.

    Apotential exception of a given context is eithera type that might be thrown as an exception or a pseudo-type,denoted by “any”, that represents the situation wherean exception of an arbitrary type might be thrown. A subexpressione1 of an expressione is animmediatesubexpression if there is no subexpressione2 ofesuch thate1 is a subexpression ofe2.

    Theset of potential exceptions of a function, functionpointer, or member function pointerf is defined asfollows:

    Theset of potential exceptions of an expressioneis empty ife is a core constant expression(7.7 [expr.const]). Otherwise, it is the union of the setsof potential exceptions of the immediate subexpressions ofe,including default argument expressions used in a function call,combined with a setS defined by the form ofe, asfollows:

    [Example: Given the following declarations

      void f() throw(int);  void g();  struct A { A(); };  struct B { B() noexcept; };  struct D() { D() throw (double); };

    the set of potential exceptions for some sample expressionsis:

    end example]

    Given a member functionf of some classX,wheref is an inheriting constructor(_N4527_.12.9 [class.inhctor]) or an implicitly-declared special memberfunction, theset of potential exceptions of the implicitly-declaredmember functionf consists of all the members from thefollowing sets:

  5. Change 14.5 [except.spec] paragraph 14 as follows:

  6. An inheriting constructor (_N4527_.12.9 [class.inhctor]) and animplicitly declaredimplicitly-declaredspecial member function (11.4.4 [special])areconsidered to have animplicitexception-specification, as follows, wheref isthe member function andS is the set of potential exceptionsof the implicitly-declared member functionf:.

    Iff is an inheritingconstructor or an implicitly declared default constructor, copyconstructor, move constructor, destructor, copy assignmentoperator, or move assignment operator, itsimplicitexception-specification specifiesthetype-idT if and only ifT isallowed by theexception-specification of a functiondirectly invoked byf's implicit definition;fallows all exceptions if any function it directly invokes allowsall exceptions, andf hastheexception-specificationnoexcept(true) ifevery function it directly invokes allows noexceptions. [Note: It follows thatf hastheexception-specificationnoexcept(true) if it invokes no other functions. —endnote] [Note: An instantiation of an inheritingconstructor template has animpliedexception-specification as if it were anon-template inheriting constructor. —end note][Example:

      struct A {    A(int = (A(5), 0))noexcept;    A(const A&) throw();    A(A&&) throw();    ~A() throw(X);  };  struct B {    B() throw();    B(const B&) = default; // Declaration ofB::B(const B&) noexcept(true)    B(B&&, int = (throw Y(), 0))throw(Y)noexcept;    ~B() throw(Y);  };  int n = 7;  struct D : public A, public B {    int * p = new (std::nothrow) int[n];    // Implicit declaration ofD::D() throw(X, std::bad_array_new_length);    // Implicit declaration ofD::D();    // Implicit declaration ofD::D(const D&) noexcept(true);    // Implicit declaration ofD::D(D&&) throw(Y);    // Implicit declaration ofD::~D() throw(X, Y);  };
  7. Change 7.6.2.7 [expr.unary.noexcept] paragraph 3 as follows:

  8. The result of thenoexcept operatorisfalsetrue ifin apotentially-evaluated context theset of potentialexceptions of the expressionwould containis empty, andfalse otherwise.

    Otherwise, the result istrue.

This resolution also resolves issues1356,1465,and1639.




[8]ページ先頭

©2009-2026 Movatter.jp