Stl: <shared_mutex>: strengthening constexpr

Created on 17 May 2020  路  6Comments  路  Source: microsoft/STL

By standard, shared_mutex constructor is not constexpr.

But it could have been made constexpr on Windows implementation.
Why isn't non-standard constexpr good (unlike nonstandard noexcept)?

question resolved

All 6 comments

We are explicitly forbidden from strengthening constexpr by WG21-N4861 16.5.5.7 [constexpr.functions]/1: "An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required."

Whereas we are explicitly permitted to strengthen noexcept: 16.5.5.13 [res.on.exception.handling]/5:
"An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification."

We've generally attempted to follow the rule against strengthening constexpr although there might be an accidental occurrence or two.

As for why the Standard specifies this, I can't give a definitive answer, but I believe there was significant concern around users accidentally taking dependencies on implementation-specific behavior, or writing code that's sensitive to implementation-specific behavior (despite the fact that strengthening noexcept is even more observable due to the noexcept operator). Speaking for myself as an implementer, early on I was very concerned about constexpr and possible unintended consequences (such as those that prevented invoke() from being constexpr for a long time); now that we have much more experience, those concerns have melted away. I personally believe it is time to allow implementations to strengthen constexpr (with the understanding that they'd be providing an implementation-specific guarantee that may be difficult/impossible to take away from users in future versions), but I don't believe that this justifies invoking the Implementer Veto.

Whereas we are explicitly permitted to strengthen noexcept: 16.5.5.13 [res.on.exception.handling]/5:
"An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification."

I'd question the interpretation of this as "you are allowed to put noexcept. They say:

That is, the C library functions can all be treated as if they are marked noexcept. This allows implementations to make performance optimizations based on the absence of exceptions at runtime.

So, I think they did not allow you to put noexcept. They did allow you to put something that works "as if noexcept for performance". Maybe throw() with MSVC behavior.

The difference is in noexcept(standard_function()). It is not allowed to change, as I understand.

If my interpretation is correct, then apparently you currently have no way to perform such optimization:

#include <iostream>

struct shared_mutex
{
    shared_mutex() {}
};

struct shared_mutex_1
{
    shared_mutex_1() noexcept {}
};

struct shared_mutex_2
{
    __declspec(nothrow) shared_mutex_2() {}
};


struct shared_mutex_3
{
    shared_mutex_3() throw() {}
};


int main()
{
    std::cout << noexcept(shared_mutex()) << '\n';
    std::cout << noexcept(shared_mutex_1()) << '\n';
    std::cout << noexcept(shared_mutex_2()) << '\n';
    std::cout << noexcept(shared_mutex_3()) << '\n';
}

Outputs:

0
1
1
1

The footnote isn't even attached to paragraph 5.

@cpplearner , yes you are right.

Paragraph 5:

An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.

According to [except.spec]/1 , noexcept specifier defines exception specification.

So, my concern is incorrect.

Regarding constexpr. There's a way to write implementation-specific code even without constexpr.

For example, if I assume static initialization of shared_mutex, this will still always work in release, due to optimization, and will only fail in debug. If I don't ever use debug build, it could be unnoticed.

I mean the purpose of the Standard to restrict relying on implementation-specific guarantees is not achieved, so probably not worth pursuing. I mean it would be good if Standard had relaxed it.

Was this page helpful?
0 / 5 - 0 ratings