Background
I'm helping debug a code base. I can't give exact details about it, but such details should be out of scope of an SO question anyway, my actual question is how I actually diagnose why an arbitrary noexcept defaulted function gets deleted anyway, not solve my codebase specific debugging issue.
The (scrubbed) version of the error I get is the following:
/.../bin/cmake --build /.../cmake-build-debug --target [current_project] -- -j 3
...
Scanning dependencies of target [other_module]
...
Scanning dependencies of target [current_project]
...
#[first instance of any error or warning that has to do with 'other_module']
/.../[current_project]/foo.cpp: In member function ‘void util::Foo::update_size(int32_t, int32_t)’:
/.../[current_project]/foo.cpp:159:70: error: use of deleted function ‘[other_module]::Bar& [other_module]::Bar::operator=([other_module]::Bar&&)’
m_Bar = createBar(number_generator, width, height);
In file included from /.../[current_project]/foo.h:11,
from /.../[current_project]/foo.cpp:6:
/.../[current_project]/external/[other_module]/include/Bar.h:69:27: note: ‘[other_module]::Bar& [other_module]::Bar::operator=([other_module]::Bar&&) noexcept’ is implicitly deleted because its exception-specification does not match the implicit exception-specification ‘’
Bar& operator=(Bar&& r) noexcept = default;
#[No other instances afterwards 'other_module']
...
gmake[3]: *** [CMakeFiles/[current_project].dir/build.make:278: CMakeFiles/[current_project].dir/foo.cpp.o] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:455: CMakeFiles/[current_project].dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:462: CMakeFiles/[current_project].dir/rule] Error 2
gmake: *** [Makefile:184: [current_project]] Error 2
Note that createBar
has the following scrubbed signature:
Bar createTracker(NumberGenerator number_generator, int width, int height);
I assume is implicitly deleted because its exception-specification does not match the implicit exception-specification
means that there is something that isn't/can't be noexcept, either in the inheritance chain of Bar
or in the member variables' move assignment operators that causes this to be an issue.
Note that the other_module
is configured as it's own target, and compiling said target does not show any warnings or errors on its own.
However I can't get clang tools or GCC to tell me where that problem is. I know it is the noexcept causing the issue, because if I remove it, the program compiles. A scrubbed version of Bar.
class Bar : public Baz{
public:
Bar(NumberGenerator number_generator,
int width, int height);
Bar(const Bar&) noexcept = default;
Bar(Bar&&) noexcept = default;
Bar& operator=(const Bar& r) noexcept = default;
//offending declaration
Bar& operator=(Bar&& r) noexcept = default;
//working declaration
//Bar& operator=(Bar&& r) = default;
private:
static bool s_value;
Bax m_bax;
Qux m_qux;
std::vector<Quux> m_quux_list;
std::vector<Corge> m_corge_list;
};
I thought that maybe if I manually implemented the definition, it would help me isolate where the violation came from, even though this should have been the information GCC gave me in the first place. Upon implementing it manually however, I found... it just compiled. no issues.
//no longer defaulted:
Bar& operator=(Bar&& r) noexcept;
//definition:
Bar &
Bar::operator=(Bar &&r) noexcept {
m_bax = std::move(r.m_bax);
m_qux = std::move(r.m_qux);
m_quux_list = std::move(r.m_quux_list);
m_corge_list = std::move(r.m_corge_list);
return *this;
}
Question
What can I actually do (ie compiler args, manual code testing, etc...) to figure out where an arbitrary "noexcept" conflict like this is happening?