0

I am trying to make a generic class that can represent any object in its most base form, bits. To do this I created a Union of an array of chars (essentially bytes) and the object that the characters make up. Unfortunately when building, I get a strange warning and error for my union.

Warning: "The destructor was implicitly defined as deleted."

Error: "Attempting to reference a deleted function."

(both occur on the line following the definition of my union)

I know that you can create custom destructors for structs, classes and unions, but there is not a need to if you are not freeing up dynamic memory, correct? Yet somehow a destructor I never defined is being automatically called and the compiler deleted it implicitly. Hence the error.

The next thing I attempted was defining a destructor within my union; it did nothing because I never asked the os for additional memory. It was once again deleted. I needed to figure out why the compiler was deleting my function and then causing an error when trying to call it after it deleted it.

I attempted looking for this error in the Microsoft visual studio list, and what it came up with was that not making the constructor public would cause this error. Additionally, looking online here I found that oftentimes the copy constructor is what causes an error because it was never defined. So i tested it by creating a class of my own and using the copy constructor = on it. It worked just fine, but gave me the same error when attempting to use it with my typeAsChar class. Interestingly enough, this error is not called when I use my class with the C default structs, int, double, etc.

Here is the code that causes the issue.

template <class type>
union typeAsChar
{
    type obj;
    char arr[sizeof(type)];
};

template <class type> 
class wontWork
{
public:

    wontWork() {/* Do nothing, no data entered */}
    wontWork(const type& obj) { foo.obj = obj; }
    ~wontWork() {/* When this goes out of scope, the default
                     destructor of the member 'type' should be called */}

    typeAsChar<type> foo;
};

int main()
{
    double testNum = 12345;
    std::string testStr = "Hello World\n";

    wontWork<std::string> test1(testStr); // has error
    std::cout << test1.foo.obj;

    wontWork<double> test2(testNum); // No error
    std::cout << test2.foo.obj;

        return 0;
}

Oddly enough, this compiles and runs perfectly with wontWork<std::string> commented out, but fails when my class is made with an object of anything other than the standard c structs (int, double, etc). Any clarification on the matter would be much appreciated.

Michael D.
  • 35
  • 5
  • `union`s are not really C++ compatible. They're really a holdover from C. In C++, you should use `std::variant` instead of unions, to avoid this problem. – Sam Varshavchik Apr 19 '19 at 01:22
  • I will try that – Michael D. Apr 19 '19 at 01:23
  • Thank you for your suggestion, but variant won't work for me because I need to pass it an object of a certain type, and then an array of characters (that would ideally be the same size as the first type passed in). The only way i could pass in the array is through a pointer to a char, but I don't want to pass in and modify the pointer. Instead I wish to modify the array of characters it points to. – Michael D. Apr 19 '19 at 01:43
  • 1
    Well, for starters, you can't actually turn "an array of characters" into a C++ `std::string`, whether by union or a variant. C++ does not work this way. You will surprised to learn that `sizeof(std::string)` is a very small value, and it's always the same size, whether the string is empty, or contains the entire text of "War And Peace". So, given that, how do you expect to accomplish your goals? Sorry, but C++ simply doesn't work this way. – Sam Varshavchik Apr 19 '19 at 01:50
  • Through an array of characters. Literally. char arr[50 /*choosing a random number here */]. Essentially a c-string, not std::string – Michael D. Apr 19 '19 at 01:54
  • `reinterpret_cast(&object)` is a well-defined way to access the bytes that make up an object (even if it's not very useful for something like `std::string`). Type-punning via union is not well-defined. – Miles Budnek Apr 19 '19 at 01:55

1 Answers1

0

Here is the answer by @Miles Budnek that worked perfectly. Thanks a lot for your info, I never knew that was a functionality in c++.

"reinterpret_cast(&object) is a well-defined way to access the bytes that make up an object (even if it's not very useful for something like std::string). Type-punning via union is not well-defined. – Miles Budnek"

Michael D.
  • 35
  • 5
  • You might want to read about POD (plain old data). Objects made of these are self contained which is critical for your approach. https://stackoverflow.com/questions/146452/what-are-pod-types-in-c – doug Apr 19 '19 at 04:35
  • I just did. Good to know it is undefined behavior to access another member of the union than the one you assigned. It seems odd to me now that my professor introduced me to unions by assigning an integer and representing it as an array of chars. That is actually undefined behavior according to c++ and should not be used – Michael D. Apr 20 '19 at 03:20