Accessing active union member - c++

Is there a simple way to understand which union member is active?
An example:
union Read_Value{
char ch;
float number;
string str;
}
Suppose a void function reads from an input file stream and initialise Read_Value on the base of the type of the variable read. Assuming I don't know how the function works, how can I understand which of the three member is active?

A bare union cannot tell you which is the active element. You have to keep track of that yourself.
Since C++17 std::variant is the "modern union". It has a index() method that tells you which is the active index. Example from cppreference:
#include <variant>
#include <string>
#include <iostream>
int main()
{
std::variant<int, std::string> v = "abc";
std::cout << "v.index = " << v.index() << '\n';
v = {};
std::cout << "v.index = " << v.index() << '\n';
}
Possible output:
v.index = 1
v.index = 0

Is there a simple way to understand which union member is active?
In general, using a tagged (or discriminated) union. This means storing some metadata (tracking which member is active) alongside the raw union.
The modern solution is indeed std::variant, which does all this for you.
If you don't have C++17 support, don't have it in your standard library's experimental or tr extensions, and for some reason can't use the Boost.variant precursor ... you can still write an old-style tagged union yourself.
I wouldn't call it simple though, at least not to do well.

Related

Is boost::beast::static_string memcopyable/trivial type?

I am looking for a string implementation with fixed upper size that can be used in memcopy environment and that is trivially constructible and copyable.
I found boost beast static_string, but IDK if my example works by accident or no?
#include <algorithm>
#include <iostream>
#include <boost/beast/core/static_string.hpp>
boost::beast::static_string<16> s1("abc");
int main(){
boost::beast::static_string<16> s2;
std::copy_n((char*)&s1, sizeof(s2), (char*)&s2);
s1.push_back('X');
std::cout << "--" << std::endl;
std::cout << s2 << std::endl;
s2.push_back('Y');
std::cout << s2 << std::endl;
std::cout << std::is_trivial_v<decltype(s2)> << std::endl;
}
note: last line says type is not trivially copyable, but it could be just that Vinnie forgott to add a type trait.
P.S. I know this is a generally bad idea, what I am replacing is even worse, just a plain C array and modifying the allocation/copying to support std::string is much much more work.
Technically no, there are user defined copy constructors and operators (both call assign) which mean the class is not trivially copyable.
These appear to exist as an optimisation, if a static_string has a large size, but only stores a small string, assign only copies the used portion of the string, plus a null terminator.
C++ does not allow for std::is_trivially_copyable to be specialized by programs, so I don't believe there is a way to get both at present.
static_string does just contain a size_t member and a CharT[N+1], so if those two were default, it would be.

Converting std::any into an unknown type

If I have a std::any of an std::string or an int, how could I cast this into the type that's contained?
std::any has type on it, however I can't use this type to cast.
Example:
#include <any>
#include <iostream>
#include <string>
int main(void) {
std::any test = "things";
std::any test2 = 123;
// These don't work
std::string the_value = (std::string) test;
int the_value2 = (int) test2;
std::cout << the_value << std::endl;
std::cout << the_value2 << std::endl;
}
You use any_cast to do the trick. For example
auto a = std::any(12); 
std::cout << std::any_cast<int>(a) << '\n';
You can find more details from cppreference
If you want to dynamically cast the value inside a std::any, you can try
if (a.type() == typeid(int)) {
cout << std::any_cast<int>(a) << endl;
} else if (a.type() == typeid(float)) {
cout << std::any_cast<float>(a) << endl;
}
If you do not have a list of types among which the any holds one, you cannot convert the any to its type and operate on it as its real type.
You can store a type in an any, and an operation in that type as a function pointer on that any. But this must be done at the moment of storage or when you do have a list (possibly with 1 element) of the possible types stored in the any.
C++ does not store sufficient information within an any to permit arbitrary code to be compiled on that type when it stores the value in the any. C++ does not permit full "reification" at runtime.
Type erasing type erasure, `any` questions? Q&A by a stackoverflow user of ill repute gives an example of how to remember some operation on the contents of the any while still forgetting the type stored.
If you do have such a list of possible types, consider using variant. any exists in the narrow window where you do not know the types stored at container design time, but do at both insert and removal.
In that narrow window, you can do runtime tests based off the typeid stored and cast to the known type using any_cast.

Cast an object value without pointers

Let's assume that A and B are two classes (or structures) having no inheritance relationships (thus, object slicing cannot work). I also have an object b of the type B. I would like to interpret its binary value as a value of type A:
A a = b;
I could use reinterpret_cast, but I would need to use pointers:
A a = reinterpret_cast<A>(b); // error: invalid cast
A a = *reinterpret_cast<A *>(&b); // correct [EDIT: see *footnote]
Is there a more compact way (without pointers) that does the same? (Including the case where sizeof(A) != sizeof(B))
Example of code that works using pointers: [EDIT: see *footnote]
#include <iostream>
using namespace std;
struct C {
int i;
string s;
};
struct S {
unsigned char data[sizeof(C)];
};
int main() {
C c;
c.i = 4;
c.s = "this is a string";
S s = *reinterpret_cast<S *>(&c);
C s1 = *reinterpret_cast<C *>(&s);
cout << s1.i << " " << s1.s << endl;
cout << reinterpret_cast<C *>(&s)->i << endl;
return 0;
}
*footnote: It worked when I tried it, but it is actually an undefined behavior (which means that it may work or not) - see comments below
No. I think there's nothing in the C++ syntax that allows you to implicitly ignore types. First, that's against the notion of static typing. Second, C++ lacks standardization at binary level. So, whatever you do to trick the compiler about the types you're using might be specific to a compiler implementation.
That being said, if you really wanna do it, you should check how your compiler's data alignment/padding works (i.e.: struct padding in c++) and if there's a way to control it (i.e.: What is the meaning of "__attribute__((packed, aligned(4))) "). If you're planning to do this across compilers (i.e.: with data transmitted across the network), then you should be extra careful. There are also platform issues, like different addressing models and endianness.
Yes, you can do it without a pointer:
A a = reinterpret_cast<A &>(b); // note the '&'
Note that this may be undefined behaviour. Check out the exact conditions at http://en.cppreference.com/w/cpp/language/reinterpret_cast

How to access C++ struct property value using index?

struct student {
string name;
int age;
};
int main() {
student a1;
cout << a1[0] << endl; //Access the first variable of the struct
cout << a2[1] << endl; //Access the first variable of the struct
}
How could I access and retrieve value from the C++ struct using index instead of using "a1.name" ??
One way to do this is by creating a tuple from the member variables and using std::tie to get at the member by index. The index would have to be known at compile time however. You could wrap this inside a member function of your struct:
#include <tuple>
#include <iostream>
struct student {
std::string name;
int age;
template<size_t I>
auto& get() {
return std::get<I>(std::tie(name, age));
}
};
int main() {
student boy{ "Paul", 12 };
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
//Change members
boy.get<0>() = "John";
boy.get<1>() = 14;
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
}
Demo
(Requires at least C++14)
In C++11, since it doesn't have automatic return type deduction unless specified, you could use std::tuple_element to specify the return type instead:
#include <tuple>
#include <iostream>
struct student {
std::string name;
int age;
template<size_t I>
using T = typename std::tuple_element<I, std::tuple<std::string, int>>::type;
template<size_t I>
T<I>& get()
{
return std::get<I>(std::tie(name, age));
}
};
int main() {
student boy{ "Paul", 12 };
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
//Change members
boy.get<0>() = "John";
boy.get<1>() = 14;
std::cout << "Name: " << boy.get<0>() << " Age: " << boy.get<1>() << std::endl;
}
Demo
You can't. At least not in the direct manner you want to do it and without partially redefining what a structure is. I will split my answer into two parts the first one explaining possible ways to get at least close to what you want and the second one explaining what you actually should do:
Getting down and dirty
There are two ways (that I can currently come up with) that might give you something to think about:
Use a wrapper class - while C++ does increase the flexibility of structure it doesn't change their purpose of a simple heterogeneous data container. It does however allow operator overloading including the [] operator. So if you create a class that contains the structure as its member (that is it wraps around the structure), you can expose the structure's data using []. This comes as close to what you want to do as possible. It does however defeat the whole purpose of using a struct since you can do that with just plain non-sturct class members but I have actually seen it not so long time ago when I was going through a C++ library that was wrapping a previous C-based version of itself in order to provide more modern features without the need of completely rewriting the C code.
Use pointer with an offset - using indexing generally suggest that the underlying container has a consistency when it comes to the blocks of data it contains. The problem is that a structure doesn't necessarily obey this since it can contain (just like in your case) multiple types of data. If you can sacrifice the heterogeneity of your structure and stick with a single data type (for example one or more doubles), you can safely use (up to the point that you have to always remember the number of members the structure has) a pointer and an increasing/decreasing offset to access its members. Just like with any sort of data when you create a standard reference (aka pointer) to something, that reference points at the address of the beginning of the memory this data is using. It is a common practice to use pointers to iterate through arrays and it works exactly like that - create a reference to your structure and the add +1, +2, ... (as many members that struct has). This makes things overly complicated though and is prone to error. As mentioned it also requires using the same type of data inside your structure. However you can also create a set of functions that handle (internally) the offsets. But this idea is similar to the class wrapper I have proposed above.
The alternatives ...
From what you have given as information I think you are looking for a completely different type of data - a dictionary, map or a list that contains some sort of custom generic data container that can hold any type of data but also stores that data's type in order to allow recasting it to its original state. Many libraries provide such containers for example Qt has the QVariant (part of the core module), boost has the boost::variant, std::tuple (or even better - named tuples) provided with your standard C++ (since C++11) and so on. I can speak about Qt in greater detail since I have more experience with it. It offers the QVariantList (a typedef for QList<QVariant>) which allows indexing. Of course all this requires you to 1)abandon your structure-thing and 2)use some more advanced containers that may or may not introduce huge drawbacks on whatever you are working on including licensing issues, memory overhead, larger binaries, handling a lot of extra library files etc.
How to access C++ struct property value using index?
You can not. C++ language has no feature that would allow this. This could be possible in a language that supports (static) reflection.
You could choose to use a std::tuple instead, which does allow indexed member access, but that's a step down in readability since you don't get to name the members.
I tried to stay as close to your example as possible but I did have to convert the age from int to string. This works and I have found it useful in one application.
struct student
{
std::string name, age;
std::string *elemtnPtr[10];
student()
{
int i=0;
elemtnPtr[i++] = &name;
elemtnPtr[i++] = &age;
}
};
void demo()
{
student a1;
a1.name = "This Works";
a1.age = "99";
std::cout << *a1.elemtnPtr[0] << std::endl;
std::cout << *a1.elemtnPtr[1] << std::endl;
}
You cannot.
Not until reflection has been introduced in C++, which should (I hope) be the case in C++20.
Some projects introduce tuples enhanced with names, but it still not real structs.

Valid use of reinterpret_cast?

Empirically the following works (gcc and VC++), but is it valid and portable code?
typedef struct
{
int w[2];
} A;
struct B
{
int blah[2];
};
void my_func(B b)
{
using namespace std;
cout << b.blah[0] << b.blah[1] << endl;
}
int main(int argc, char* argv[])
{
using namespace std;
A a;
a.w[0] = 1;
a.w[1] = 2;
cout << a.w[0] << a.w[1] << endl;
// my_func(a); // compiler error, as expected
my_func(reinterpret_cast<B&>(a)); // reinterpret, magic?
my_func( *(B*)(&a) ); // is this equivalent?
return 0;
}
// Output:
// 12
// 12
// 12
Is the reinterpret_cast valid?
Is the C-style cast equivalent?
Where the intention is to have the bits located at &a interpreted as a
type B, is this a valid / the best approach?
(Off topic: For those that want to know why I'm trying to do this, I'm dealing with two C libraries that want 128 bits of memory, and use structs with different internal names - much like the structs in my example. I don't want memcopy, and I don't want to hack around in the 3rd party code.)
In C++11, this is fully allowed if the two types are layout-compatible, which is true for structs that are identical and have standard layout. See this answer for more details.
You could also stick the two structs in the same union in previous versions of C++, which had some guarantees about being able to access identical data members (a "common initial sequence" of data members) in the same order for different structure types.
In this case, yes, the C-style cast is equivalent, but reinterpret_cast is probably more idiomatic.