Jump to content
sumit_tuwien

Non Constructible but Copyable !

Recommended Posts

Hello All,

I found out this issue while I was playing with some SystemC stuffs (During meta-programming). This is a C++ question which I separated out from the SystemC implementation. I could have gone to pure C++ forum but since I use this forum, I believe if I ask here people will be benefited more.

I observed that if I explicitly delete only constructor and destructor  of a class then the resultant implementation deletes copy constructor & move constructor, but the compiler still makes copy assignment and move assignment operators implicitly available! Which in turn makes assignment possible!

My question is what is the rational of this? What is the use case where this can be used. Following is an example code for reference:

 

# ifndef MOEGLICH_H_
# define MOEGLICH_H_

# include <cstdint>

class Moeglich final
{
public :

   explicit
   Moeglich()                                 = delete   ;
  ~Moeglich()                                 = delete   ;

/*
// With explicit deletion
   Moeglich& operator=(const Moeglich& other) = delete   ; 
   Moeglich(const Moeglich& other)            = delete   ;
   Moeglich&& operator=(Moeglich&& other)     = delete   ; 
   Moeglich(Moeglich&& other)                 = delete   ;
*/

   static constexpr uint16_t Egal(const uint8_t& var_) noexcept
   {
      return static_cast< uint16_t > ( var_ ) ;
   }

};

# endif

# include <cstdlib>
# include <iostream>
# include <type_traits>

int main(int argc, char* argv[])
{

   std::cout << std::boolalpha 
             << "Is constructible      : " << std::is_constructible<Moeglich>::value        << std::endl 
             << "Is destructible       : " << std::is_destructible<Moeglich>::value         << std::endl 
             << "Is copy constructible : " << std::is_copy_constructible<Moeglich>::value   << std::endl 
             << "Is move constructible : " << std::is_move_constructible<Moeglich>::value   << std::endl 
             << "Is copy assignable    : " << std::is_copy_assignable<Moeglich>::value      << std::endl 
             << "Is move assignable    : " << std::is_move_assignable<Moeglich>::value      << std::endl 
             << "Is assignable         : " << std::is_assignable<Moeglich, Moeglich>::value << std::endl 
              ;

/* Following were what I wanted to bar anyway :

   const Moeglich mom {} ;
   Moeglich pop {} ;
   Moeglich foo {} ;
   foo = mom ;
   foo = std::move(pop) ;

*/

   return EXIT_SUCCESS ;

}



 

Regards,

Sumit 

Share this post


Link to post
Share on other sites

Hi Sumit,

Quoting http://en.cppreference.com:
 

Some member functions are special: under certain circumstances they are defined by the compiler even if not defined by the user. They are:

 

So in the code you show you just delete the default constructor and the destructor. Obviously this does not make sense as you cannot construct any object since you do not have a parameterized constructor. But if you have one this declaration makes sense: the user of this class cannot create a default object, he has to provide some parameters. Deleting the destructor prohibits the creation of an object on the stack, you can only create them on the heap (and never release the memory except you use placement new on a pre-allocated area).

But the the standard comittee has a special section on this in the C++ core Guidelines: C.21: If you define or =delete any default operation, define or =delete them all

BTW, if you inherit from a class having a deleted destructor the destructor of the child is also deleted

HTH

-Eyck

Share this post


Link to post
Share on other sites

Hello Eyck,

Quote

But the the standard comittee has a special section on this in the C++ core Guidelines: C.21: If you define or =delete any default operation, define or =delete them all

This is an amazing pointer.

I see I have created a lot of confusions by vaguely putting some code and not mentioning the intent. I will never construct this object. All I am interested is accessing

const uint8_t duh { 5 } ;
const uint16_t notEgal { Moeglich::Egal(duh) } ;

Here is what is important for me: Sometimes, I need partial template specialization of functions which is not allowed which can be enabled if I put this function inside a template class.

Your link, very clearly lays down the rule. My expectation from the compiler was wrong and my use-case cannot be understood in a special way by the compiler.

Meanwhile, I also asked help from stackoverflow.com in here (I generally do not do that, because they are champions in downvoting questions). You can see how many confusing and different answers from people.

Please note:: Since I always explicitly mention all 6 special member functions, it was fine. This was accidentally found when in one place I missed 4 of them and started wondering. Glad that I did that mistake, which enabled me to learn something and correct some mistakes in my understanding.

Thanks for the great help.

Regards,

Sumit

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×