Reputation: 380
Consider the following example:
#include <chrono>
using T = std::chrono::system_clock::time_point;
struct A
{
A() = default;
explicit A(T time) : time{time}
{
}
T time{};
};
A foo()
{
return A{};
}
When I compile this code with GCC 9.2.0, it will generate the following warning:
$ g++ -c noexcept.cpp -o noexcept.cpp.o --std=c++17 -Wnoexcept
noexcept.cpp:18:12: warning: noexcept-expression evaluates to ‘false’ because of a call to ‘constexpr std::chrono::time_point<_Clock, _Dur>::time_point() [with _Clock = std::chrono::_V2::system_clock; _Dur = std::chrono::duration<long int, std::ratio<1, 1000000000> >]’ [-Wnoexcept]
18 | return A{};
| ^
I do not understand the meaning of this warning. It is only generated when the second constructor is in place (even though it is never called).
The warning talks about a noexcept-expression that is being evaluated. As I don’t see any such expression, I suppose there is something like an implicit noexcept-expression in the first constructor. I don’t understand why something like that should lead to a warning, though. And why does it make a difference if the second constructor is there?
Could you please shed some light onto this and explain what the problem with this code is?
Upvotes: 6
Views: 1485
Reputation: 238281
This looks like a false positive diagnostic to me. Because there indeed doesn't appear to be any noexcept-expression that would evaluate to false because of that function.
P.S. The behaviour doesn't reproduce if I remove the default member initialiser from A::time
. As far as I know, this has no semantic difference in the example program.
Upvotes: 1
Reputation: 119034
It seems you explicitly opted into -Wnoexcept
. The meaning of the flag is explained here: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html
Warn when a noexcept-expression evaluates to false because of a call to a function that does not have a non-throwing exception specification (i.e. throw() or noexcept) but is known by the compiler to never throw an exception.
In this case, I would have to guess that the compiler is implicitly evaluating a noexcept-expression involving T{}
in order to determine whether the defaulted default constructor of A
should be implicitly declared noexcept
. The warning arises because the compiler can determine that the default constructor of time_point
never throws, yet said default constructor is not declared noexcept
. See here for definition.
There is no issue with your code. The root cause of the warning is that time_point
doesn't have the appropriate noexcept
declaration. However, this is true for many standard library constructors, and it will take a long time to fix all of them. So, in the meantime, this warning seems to mostly add noise. If you still want to compile with this flag, you could define A::A()
yourself as A() noexcept {}
. (In this case you wouldn't be giving up triviality, since T::T()
isn't trivial anyway.)
Upvotes: 6