c++11 - Usage of noexcept in derived classes -
i encounter issue while using noexcept
specifier on derived classes, more precisely when parent abstract class (has protected
constructors).
hereafter example of way declare classes.
- with
public
constructor in base class: ok. - same code
protected
, derived class no more "nothrow movable".
do miss something? std::is_nothrow_move_constructible
correct traits use in derived class declarations or should use else?
thanks answers.
#include <cstdlib> #include <iostream> class baseok { public: baseok ( baseok&& other ) noexcept {} }; class basenok { protected: basenok ( basenok&& other ) noexcept {} }; class childok : public baseok { public: childok ( childok&& other ) noexcept ( std::is_nothrow_move_constructible < baseok >::value ) : baseok ( std::move ( other ) ) {} }; class childnok : public basenok { public: childnok ( childnok&& other ) noexcept ( std::is_nothrow_move_constructible < basenok >::value ) : basenok ( std::move ( other ) ) {} }; int main () { std::cout << std::boolalpha; std::cout << "is baseok move constructible? " << std::is_move_constructible < baseok >::value << '\n'; std::cout << "is childok move constructible? " << std::is_move_constructible < childok >::value << '\n'; std::cout << '\n'; std::cout << "is baseok nothrow move constructible? " << std::is_nothrow_move_constructible < baseok >::value << '\n'; std::cout << "is childok nothrow move constructible? " << std::is_nothrow_move_constructible < childok >::value << '\n'; std::cout << '\n'; std::cout << "is basenok move constructible? " << std::is_move_constructible < basenok >::value << '\n'; std::cout << "is childnok move constructible? " << std::is_move_constructible < childnok >::value << '\n'; std::cout << '\n'; std::cout << "is basenok nothrow move constructible? " << std::is_nothrow_move_constructible < basenok >::value << '\n'; std::cout << "is childnok nothrow move constructible? " << std::is_nothrow_move_constructible < childnok >::value << '\n'; std::cout << std::endl; return exit_success; }
output:
baseok move constructible? true childok move constructible? true baseok nothrow move constructible? true childok nothrow move constructible? true basenok move constructible? false childnok move constructible? true basenok nothrow move constructible? false childnok nothrow move constructible? false
___ edit ____________________________________________________________
after searching around while, , regarding andswer of oleg bogdanov, unfortunately seems not possible combine protected
constructors usage of noexcept ( is_nothrow_... )
.
i writting abstract classes , declared constructors protected
documentation purposes only. now, constructors public
i'm facing problem:
as abstract class cannot instanciated, std::is_nothrow_move_constructible<baseclass>
returns false
, derived classes can never tagged not throwing exceptions if not.
see example below:
#include <cstdlib> #include <iostream> class foo { public: foo ( foo&& other ) noexcept {} virtual ~foo () = 0; // removing '= 0' makes both outputs print 'true'. }; foo::~foo () {} class bar : public foo { public: bar ( bar&& other ) noexcept ( std::is_nothrow_move_constructible < foo >::value ) : foo ( std::move ( other ) ) {} }; int main () { std::cout << std::boolalpha; std::cout << "foo: " << std::is_nothrow_move_constructible < foo >::value << '\n'; std::cout << "bar: " << std::is_nothrow_move_constructible < bar >::value << '\n'; return exit_success; }
output:
foo: false bar: false
when evaluating true
is_move_constructible works is_constructible, in turn says
t object or reference type , variable definition t obj(std::declval()...); well-formed
my guess in case, definition basenok obj(...)
not well-formed, because neither have public default ctor (its implicitly removed) nor other accessible ctor (protected not), evals false
. (the definition of well-formeness arguable though)
childnok still move_constructible because made move ctor public, other cases eval false
because std::is_move_constructible < basenok >::value
false
edit: edited question, note section of is_constructible mentions
in many implementations, is_nothrow_constructible also checks if destructor throws because effectively noexcept(t(arg))
when keep destructor pure virtual, fails check.
i not sure if it's oversight or by-design of type traits, issues covered in lwg issue 2116
i'm not proposing scalable solution here, why not mark derived classes unconditionally noexcept now, given base noexcept() too
Comments
Post a Comment