Suppose I have a struct that contains a union with const
members, like so:
struct S
{
// Members
const enum { NUM, STR } type;
union
{
const int a;
const std::string s;
};
// Constructors
S(int t_a) : type(NUM), a(t_a);
S(const std::string & t_s) : type(STR), s(t_s);
};
So far, so good. But now say I want to write a copy-constructor for this type.
It doesn't seem like this involves doing anything nefarious, but since I need to initialize the const members in member initializers I don't see how to do this based on logic that depends on the type
member.
Questions:
Is it possible to write this constructor?
If not, is this essentially a syntactic oversight, or is there some fundamental reason that the language can't support such a thing?
A union can have member functions (including constructors and destructors), but not virtual functions.
In C++, a Copy Constructor may be called for the following cases: 1) When an object of the class is returned by value. 2) When an object of the class is passed (to a function) by value as an argument. 3) When an object is constructed based on another object of the same class.
Defining a Union union Data { int i; float f; char str[20]; } data; Now, a variable of Data type can store an integer, a floating-point number, or a string of characters. It means a single variable, i.e., same memory location, can be used to store multiple types of data.
A copy constructor has as its first parameter a (possibly const or volatile) reference to its own class type. It can have more arguments, but the rest must have default values associated with them.
Yes, it is possible to write copy constructor here. Actually it is already done inside std::variant
implementation, which shall support const
-types among others. So your class S
can be replaced with
using S = std::variant<const int, const std::string>;
But if for dome reason you cannot use std::variant
then copy-constructor can be written using std::construct_at
function as follows:
#include <string>
struct S {
const enum { NUM, STR } type;
union {
const int a;
const std::string s;
};
S(int t_a) : type(NUM), a(t_a) {}
S(const std::string & t_s) : type(STR), s(t_s) {}
S(const S & rhs) : type(rhs.type) {
if ( type == NUM ) std::construct_at( &a, rhs.a );
if ( type == STR ) std::construct_at( &s, rhs.s );
}
~S() {
if ( type == STR ) s.~basic_string();
}
};
int main() {
S s(1);
S u = s;
S v("abc");
S w = v;
}
Demo: https://gcc.godbolt.org/z/TPe8onhWs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With