Convert STL map into a struct - c++

I have a std::map<string, double> whose members look something like:
X = [{"N", 200}, {"sigma", 1.0}, {"T", .2}]
Now, given the struct foo Y:
struct foo {
int N;
double T;
};
Can I programmatically map the key/value pairs X -> Y without writing a custom class for each X -> Y type mapping? Note that:
X["sigma"] is not in Y, i.e. the mapping is not necessarily one-to-one
The type of Y.N is an int while X["N"] is a double.
I suspect the answer is no, unless some trickery is done at compile time.
Edit: It may not be clear what I'm looking for. A pseudo-code version for this example would look something like:
if("N" in X) -> Y.N = X["N"];
if("T" in X) -> Y.T = X["T"];
Or programmatically:
for key in Y:
if (key in X) -> Y.key = X[key]

No. C++ has no concept of reflection. At compile time, there's no "foo::N" string anymore. The compiler has converted all occurances of foo::N in the source code to a 0 byte offset within Foo objects. Also, you cannot enumerate class members at compile time.

You want to set a field in an object of structure type based on the value of key in the map's elements (which is a string). So, no it cannot be done at compile time.

Related

Is there a way to store auto value in c++ map? [duplicate]

This question already has answers here:
C++ std::map holding ANY type of value
(8 answers)
Closed 1 year ago.
Hey I'm new with c++ and I'm trying to create a map wich can store multiples types :
map<sting, `auto`> test_map;
test_map["first elem"] = 1;
test_map["second elem"] = 'c';
Wich obviously gets me some errors.
I've been looking a bit online and I have found interesting things but not an answer. Maybe I miss a bit of c++ vocabulary.
I would also try with some kind of class wich stores about any types and I don't know if it can works.
map<string, `my_class`> test_map;
map["first_elem"] = my_class("string");
map["first_elem"] = my_class(12);
Thank you for helping !
The auto keyword doesn't mean you can assign multiple value types to the same storage, it's merely an automatic type deduction tool in c++ useful when you deal with complex type names or purely unwritable types (such as capturing lamdas) eg.:
void foo()
{
bool b = true;
auto l = [&]() -> bool { return !b; };
}
If you want to store values of different (or any) types in the same storage space try using either std::varian or std::any (both require c++17 or higher).
std::variant allows you to store one of the earlier specified types and doesn't do additional allocations (it's size is enough to hold any object of specified type). It's a type safe alternative to unions.
void foo()
{
std::map<std::string, std::variant<int, float, char>> c; // this can only map int, float and char to std::string
}
std::any can store any type you want but will allocate when necessary.
void foo()
{
std::map<std::string, std::any> c; // this can map any type of value to std::string
}

How to use type-level functions to create static types, dynamically?

In TypeScript, there are type-level functions that allow creating new types based on given literal types/specifications (see Mapped Types, Conditional Types, etc.).
For instance, here is such a function, let say provided by a lib author:
type FromSpec<S> = {
[K in keyof S]: S[K] extends "foo" ? ExampleType : never
};
Its purpose is, given a specification S in the form of a map of string keys and arbitrary literals, it creates a new type in the form of a map with the same set of keys and with values transformed. If a the value is the literal "foo" then it becomes the type ExampleType, otherwise the value is rejected by transforming it into the bottom type never.
Then, an end-user can make use of this function to create new types following the above explanation:
type Example = FromSpec<{some_key: "foo", another_key: "bar"}>
// = {some_key: ExampleType, another_key: never}
It's noteworthy that the lib author doesn't know about what exact type a given end-user may want, and thus provides him with a function to create the ones he needs. On the other hand, the end-user can create an infinite set of new types as long as he complies with the function's capabilities.
You can play around this simple example, here.
The question is about how this kind of "dynamism" is expressible in other typed languages (e.g., ReasonML/OCaml, Scala, Haskell). Or how, as an end-user, to create new types, at compile-time, by using type-level functions, provided by a lib author (as one would usually do at runtime with value-level functions)?
It's important to note that the question is not about which language is better, etc. It's about finding the most straightforward and explicit way to express such capabilities. Here we saw an example in TypeScript, but is there any more natural way in any other language?
Given Scala is one of the tagged languages, here is a solution in Dotty (aka. Scala 3). Take this with a grain of salt, since Dotty is still under development. Tested with Dotty version 0.24.0-RC1, here is a Scastie that proves this actually compiles.
Scala doesn't have the same sort of built-in type machinery as TypeScript for manipulating records. Not to fear, we can roll our own!
import deriving._
// A field is literally just a tuple of field name and value
type Field[K, V] = (K, V)
// This just helps type-inference infer singleton types in the right places
def field[K <: String with Singleton, V <: Singleton](
label: K,
value: V
): Field[K, V] = label -> value
// Here is an example of some records
val myRec1 = ()
val myRec2 = field("key1", "foo") *: field("key2", "foo") *: ()
val myRec3 =
field("key1", 1) *: field("key2", "foo") *: field("key3", "hello world") *: ()
Then, FromSpec can be implemented using a match-type. The never type in TypeScript is called Nothing in Scala/Dotty.
// Could be defined to be useful - `trait` is just an easy way to bring a new type in
trait ExampleType
val exampleValue = new ExampleType {}
type FromSpec[S <: Tuple] <: Tuple = S match {
case Field[k, "foo"] *: rest => Field[k, ExampleType] *: FromSpec[rest]
case Field[k, v] *: rest => Field[k, Nothing] *: FromSpec[rest]
case Unit => Unit
}
Finally, let's use FromSpec:
def myRec1Spec: FromSpec[myRec1.type] = ()
def myRec2Spec: FromSpec[myRec2.type] =
field("key1", exampleValue) *: field("key2", exampleValue) *: ()
def myRec3Spec: FromSpec[myRec3.type] = ??? // no non-diverging implementation
Is it possible to express the same kind of "dynamism" or something close to it in another typed language (e.g., ReasonML/OCaml, Scala, Haskell).
Yes, dynamic types are fully supported by the OCaml/ReasonML type system and are widely used. You can express quite complex dynamic typing rules, e.g., build your hierarchies, implement ad-hoc polymorphism and so on. The main ingredients of the solution is using extensible GADT, first-class modules, and existentials. See this answer as one of the example or this discussion for the general case of universal values, there are also multiple libraries that provide various dynamic typing capabilities in OCaml. Another example is BAP's Core Theory library that has a very complex type hierarchy for value sorts, which includes precise type specifications for various number representations, including floating-point numbers, memories, etc.
To make the answer complete, this is how you can implement your fromSpec in OCaml, first we define type that will be bearing the tag for dynamic typing, underneath the hood this is just an integer, but with associated type which it is witnessing,
type 'a witness = ..
To create a new witness (basically incrementing this id) we will use first class modules and append a new constructor using +=
module type Witness = sig
type t
type _ witness += Id : t witness
end
type 'a typeid = (module Witness with type t = 'a)
let newtype (type u) () =
let module Witness = struct
type t = u
type _ witness += Id : t witness
end in
(module Witness : Witness with type t = u)
The type equality proof (the value that proofs to the compiler that two types are the same since they are both using the constructor with the same identity), is commonly represented as ('a,'b) eq type,
type ('a,'b) eq = Equal : ('a,'a) eq
And this is how we implement the cast function,
let try_cast : type a b. a typeid -> b typeid -> (a,b) eq option =
fun x y ->
let module X : Witness with type t = a = (val x) in
let module Y : Witness with type t = b = (val y) in
match X.Id with
| Y.Id -> Some Equal
| _ -> None
finally, your fromSpec,
type spec {
data : 'a;
rtti : 'a typeid
}
let example_type = newtype ()
let example = {
data = 42;
rtti = example_type; (* witnesses that data is `int` *)
}
let fromSpec = try_cast example_type
Disclaimer: I'm not a C++ programmer, so don't take this answer to be the proper way to do it in C++. It is just one way to do it that is extremely brittle and is probably mostly wrong.
//I've used char pointers below, because it's not possible to directly write string //literals in templates without doing some more complex stuff that isn't relevant here
//field1 and field2 are the names of the fields/keys
const char field2[] = "field2";
const char field1[] = "field1";
//foo and bar are the strings that determine what the
//type of the fields will be
const char foo[] = "foo";
const char bar[] = "bar";
//This represents a key and the determining string (foo/bar)
template <const char * name, const char * det>
struct Named {};
//What the type of the field will be if it maps to "foo"
struct ExampleType {
std::string msg;
};
//The end of a cons structure
struct End{};
//A cons-like structure, but for types
template <typename T, typename N>
struct Cons {
typedef T type;
typedef N Next;
};
//This'll be used to create new types
//While it doesn't return a type, per se, you can access the
//"created" type using "FromSpec<...>::type" (see below)
template <typename T>
struct FromSpec;
//This will handle any Named template where the determining string
//is not "foo", and gives void instead of ExampleType
template <const char * name, const char * det, typename rest>
struct FromSpec<Cons<Named<name, det>, rest>> {
//Kinda uses recursion to find the type for the rest
typedef Cons<void, typename FromSpec<rest>::type> type;
};
//This will handle cases when the string is "foo"
//The first type in the cons is ExampleType, along with the name
//of the field
template <const char * name, typename rest>
struct FromSpec<Cons<Named<name, foo>, rest>> {
typedef Cons<ExampleType, typename FromSpec<rest>::type> type;
};
//This deals with when you're at the end
template <>
struct FromSpec<End> {
typedef End type;
};
Now you can use it like this:
typedef Cons<Named<field1, foo>, Cons<Named<field2, bar>, End>> C;
//Notice the "::type"
typedef FromSpec<C>::type T;
T is equivalent to Cons<ExampleType, Cons<void, End>>
You can then access the types inside like so:
typedef T::type E; //Equivalent to ExampleType
typedef T::type::Next N; //Equivalent to Cons<void, End>
typedef N::type v; //Equivalent to void
Example usage
int main() {
ExampleType et = { "This is way too complicated!" };
//You can kinda have values of type "void", unfortunately,
//but they're really just null
// v
N inner = { nullptr, new End() };
T obj = { &et, &inner };
Cons<ExampleType, Cons<void, End>> obj2 = obj;
std::cout << et.msg << std::endl;
}
Prints "This is way too complicated!"
Link to repl.it
Feel free to edit my answer if it has mistakes or if it could be otherwise improved. I mostly just tried to translate the answer by #Alec into C++.

What is the preferred syntax for initializing an object to pass as an argument in C++08?

Let's say I have a struct that I am just using as an aggregate data holding device. As an example, a struct below holds two integer values. Let's assume I have a vector of these structs called myVec and I want to add a new struct to the vector with push_back. My understanding is that in C++11 and after one can achieve this without needing to make a named variable and passing that variable as an argument but instead can do the following.
struct coordinate {
int y;
int x;
};
//assume an initialized vector<coordinate> myVec
//and two ints newY, newX not known at compile time
myVec.push_back( {newY,newX});
Based on the Notes section of https://en.cppreference.com/w/cpp/language/aggregate_initialization,
It seems like this is an example of using aggregate initialization in a constructor initializer list but I might be wrong about that. That source indicates that this syntax doesn't work pre-C++11 and while it works with MSVS2017 it doesn't with Visiual C++ for Python which is what I am targeting. Is there a syntax pre-C++11 that would allow me to add another struct to the vector without first making a named struct variable and passing that named variable to the push_back function? While this is a single example of what I'm trying to accomplish, I will have several such vectors in my project and the structs won't always be simple pairs of ints. I would prefer to avoid having several "temp" dummy variables floating around as placeholders for arguments simply because it feels cleaner to avoid having them floating around. An example of what I would prefer to avoid but will use if necessary is given below. The example adds the list of all coordinates where both the x and y values are between 0 and 9 inclusive to the vector.
coordinate temp = {0,0};
for (int r = 0; r < 10; ++r){
for (int c = 0; c < 10; ++c){
temp.y = r;
temp.x = c;
myVec.push_back(temp);
}
}
Just give your struct a constructor:
struct coordinate {
int x, y;
coordinate( int ax, int ay ) : x(ax), y(ay) {}
};
You can then say things like:
myVec.push_back( coordinate( 12, 42 ) );

Tree in C++11 tuple with RTTI

I want to implement a simple tree in C++11 tuple with a Python fashion. In Python, we can use type(obj) to check run-time object type, and pass object with different type to one function, I have write pseudo code for calc(), how to do it in c++?
I try to print typeid(child1).name() and typeid(tree).name(), they are 'St5tupleIIciiEE' and 'St5tupleIIcS_IIciiEES0_EE'.
My environment is g++ 4.8.1. Thanks!
// pseudo code
int calc(tuple tree) {
symbol = type(get<0>(tree));
l_child = type(get<1>(tree));
r_child = type(get<2>(tree));
l = (type(l_child) == tuple) ? calc(l_child) : l_child;
r = (type(r_child) == tuple) ? calc(r_child) : r_child;
return l symbol r;
}
int main()
{
auto l_child = make_tuple('*', 1, 2);
auto r_child = make_tuple('-', 5, 1);
auto tree = make_tuple('+', l_child, r_child);
cout << calc(tree) << endl;
}
Python and C++ are very different languages. C++ is statically typed, Python is not. Transplanting Python techniques to C++ may or may not work. In this case it won't work.
In Python, there is only one tuple class, able to represent any tuple; in C++ there is an infinite number of tuple types, each one able to hold specific kinds of data. They are not interchangeable, as your experiment with typeid aptly demonstrates.
In C++, you cannot hold an arbitrary tree in a tuple. Write a tree class (or better, a class template).
Edit: technically, if you combine tuples with pointers and unions, you can get away with tuples. This is however not recommended. Your tree is going to be your central abstraction, exposing such low level details as pointers and unions is counterproductive and should be avoided. The C++ way is to write a class, stick to it.
It's unreal, since result of typeid().name is implementation-defined.
const char* name() const noexcept;
Returns: An implementation-defined ntbs.
However, here, you cannot use ternary operator, since calc(l_child) will be evaluated at compile-time, so if l_child is not tuple, compilation will be failed.
You can use some type-traits (or overloading), since tuple members are known at compile-time.
int calc(int value)
{
return value;
}
template<typename Left, typename Right>
int calc(const std::tuple<char, Left, Right>& tuple)
{
char symbol = std::get<0>(tuple);
Left l_child = std::get<1>(tuple);
Right r_child = std::get<2>(tuple);
int l = calc(l_child);
int r = calc(r_child);
return l /*symbol*/, r;
}
Live example

How to iterate through variable members of a class C++

I'm currently trying to do a complicated variable correction to a bunch of variables (based on normalizing in various phase spaces) for some data that I'm reading in. Since each correction follows the same process, I was wondering if there would be anyway to do this iteratively rather than handle each variable by itself (since I need to this for about 18-20 variables). Can C++ handle this? I was told by someone to try this in python but I feel like it could be done in C++ in some way... I'm just hitting a wall!
To give you an idea, given something like:
class VariableClass{
public :
//each object of this class represents an event for this particlular data set
//containing the following variables
double x;
double y;
double z;
}
I want to do something along the lines of:
for (int i=0; i < num_variables; i++)
{
for (int j=0; j < num_events; j++)
{
//iterate through events
}
//correct variable here, then move on to next one
}
Thanks in advance for any advice!!!
I'm assuming your member variables will not all have the same type. Otherwise you can just throw them into a container. If you have C++11, one way you could solve this problem is a tuple. With some template metaprogramming you can simulate a loop over all elements of the tuple. The function std::tie will build a tuple with references to all of your members that you can "iterate" like this:
struct DoCorrection
{
template<typename T>
void operator()(T& t) const { /* code goes here */ }
};
for_each(std::tie(x, y, z), DoCorrection());
// see linked SO answer for the detailed code to make this special for_each work.
Then, you can specialize operator() for each member variable type. That will let you do the appropriate math automatically without manually keeping track of the types.
taken from glm (detail vec3.incl)
template <typename T>
GLM_FUNC_QUALIFIER typename tvec3<T>::value_type &
tvec3<T>::operator[]
(
size_type i
)
{
assert(i < this->length());
return (&x)[i];
}
this would translate to your example:
class VariableClass{
public :
//each object of this class represents an event for this particlular data
double x;
double y;
double z;
double & operator[](int i) {
assert(i < 3);
return (&x)[i];
}
}
VariableClass foo();
foo.x = 2.0;
std::cout << foo[0] << std::endl; // => 2.0
Althought i would recomment glm, if it is just about vector math.
Yes, just put all your variables into a container, like std::vector, for example.
http://en.cppreference.com/w/cpp/container/vector
I recommend spending some time reading about all the std classes. There are many containers and many uses.
In general you cannot iterate over members without relying on implementation defined things like padding or reordering of sections with different access qualifiers (literally no compiler does the later - it is allowed though).
However, you can use a the generalization of a record type: a std::tuple. Iterating a tuple isn't straight-forward but you will find plenty of code that does it. The worst here is the loss of named variables, which you can mimic with members.
If you use Boost, you can use Boost.Fusion's helper-macro BOOST_FUSION_ADAPT_STRUCT to turn a struct into a Fusion sequence and then you can use it with Fusion algorithms.