Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is `this` allowed inside a noexcept specification?

I have some code which requires me to use *this, but I want it to be noexcept friendly:

struct foo;

// Would actually be something with conditional noexcept
void do_something(foo&);

struct foo {
    void fn()
        noexcept(noexcept(::do_something(*this)))
    {
        ::do_something(*this);
    }
};

However, gcc rejects this:

<source>:7:43: error: invalid use of 'this' at top level
         noexcept(noexcept(::do_something(*this)))

If I just access a member, gcc is fine:

void do_something(int);

struct bar {
    int x;

    void fn()
        noexcept(noexcept(::do_something(x)))
    {
        ::do_something(x);
    }
};

However, if I access the member through the this pointer, gcc complains again:

struct baz {
    int x;

    void fn()
        noexcept(noexcept(::do_something(this->x)))
    {
        ::do_something(this->x);
    }
};

Diagnostic:

<source>:7:42: error: invalid use of 'this' at top level
         noexcept(noexcept(::do_something(this->x)))

Every other compiler I tried accepts using this inside the noexcept specification, but I don't actually know if it's gcc that has the bug or all the other compilers.

Can the keyword this be used inside a noexcept specification?

like image 957
Justin Avatar asked Oct 24 '18 16:10

Justin


People also ask

What does Noexcept mean?

The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.

Is Noexcept required?

Never. noexcept is for compiler performance optimizations in the same way that const is for compiler performance optimizations. That is, almost never. noexcept is primarily used to allow "you" to detect at compile-time if a function can throw an exception.

When should you declare your functions as Noexcept?

The dynamic exception specification, or throw(optional_type_list) specification, was deprecated in C++11 and removed in C++17, except for throw() , which is an alias for noexcept(true) . We recommended you apply noexcept to any function that never allows an exception to propagate up the call stack.

What if a Noexcept function throws an exception?

When an exception is thrown from a function that is declared noexcept or noexcept(true) , std::terminate is invoked. When an exception is thrown from a function declared as throw() in /std:c++14 mode, the result is undefined behavior. No specific function is invoked.


1 Answers

Yes, it is allowed. [expr.prim.this]p2 says:

If a declaration declares a member function or member function template of a class X, the expression this is a prvalue of type “pointer to cv-qualifier-seq X” between the optional cv-qualifier-seq and the end of the function-definition, [...].

The cv-qualifier-seq refers to the cv qualifiers of the member function, which appear before the noexcept specifier:

parameters-and-qualifiers:
    ( parameter-declaration-clause ) cv-qualifier-seq[opt] ref-qualifier[opt] 
      noexcept-specifier[opt] attribute-specifier-seq[opt]

So, this is a valid expression to use in the noexcept-specifier. This was a DR (cwg1207), which gcc doesn't implement. The bug report.

like image 51
Rakete1111 Avatar answered Oct 13 '22 18:10

Rakete1111