I have some code like this
#include <chrono>
using std::chrono::steady_clock;
using std::chrono::time_point;
class MyClass
{
public:
MyClass() noexcept = default;
MyClass(MyClass const&) noexcept = default;
MyClass(MyClass&&) noexcept = default;
MyClass& operator=(MyClass const&) noexcept = default;
MyClass& operator=(MyClass&&) noexcept = default;
private:
time_point<steady_clock> timestamp;
};
int main() {
MyClass myObject;
MyClass myOtherObject(myObject);
return 0;
}
Trying to compile it results in
prog.cpp: In function ‘int main()’:
prog.cpp:18:10: error: use of deleted function ‘constexpr MyClass::MyClass()’
MyClass myObject;
^~~~~~~~
prog.cpp:8:5: note: ‘constexpr MyClass::MyClass() noexcept’ is implicitly deleted because
its exception-specification does not match the implicit exception-specification ‘’
MyClass() noexcept = default;
But compiles fine if I remove the noexcept
specifier for the default constructor:
MyClass() = default;
MyClass(MyClass const&) noexcept = default;
MyClass(MyClass&&) noexcept = default;
MyClass& operator=(MyClass const&) noexcept = default;
MyClass& operator=(MyClass&&) noexcept = default;
So I have 2 questions:
noexcept
? I mean, as far as I understand it only contains an integer of some type representing the time since epoch, which is supposed to be 0 for the default constructor if I believe cppreferencenoexcept
from only the default constructor work? If the compiler says that it had generated MyClass()
and not MyClass() noexcept
and therefore deleted it, it should be the same for MyClass(MyClass const&)
, right? But the compiler lets me do the copy without complaining here...
- How come time_point's default constructor isn't noexcept?
When noexcept
first went into the standard in C++11 the committee was very hesitant to "over apply" it. noexcept
is much easier to add to the standard than to remove. In applying it conservatively, "conditional" noexcept
was often shunned.
I would like to see "conditional" noexcept
applied to <chrono>
. For the time_point
default constructor the noexcept
would be conditional on if rep
is noexcept
default constructible. rep
doesn't have to be an integer. It might be a class type with a throwing default constructor. But the specialization steady_clock::time_point
would always be noexcept
because it's rep
is required to be integral.
- Why does removing noexcept from only the default constructor work?
Because time_point
has a user-declared default constructor but a compiler-supplied copy constructor. This is one example of how compiler-supplied special members can be so much "smarter" than user-declared ones.
The compiler-supplied copy constructor of time_point
effectively already has a "conditional" noexcept
. You get this for free by writing less code. Had the time_point
default constructor been compiler-supplied (which it should have been), then it would work in your example too.