my code was
#include <iostream>
#include <list>
#include <functional>
using namespace std;
void tes(std::string s)
{
cout << "tes " << s << '\n';
}
void tes2(std::string s)
{
cout << "tes " << s << '\n';
}
void tes3(std::string s)
{
cout << "tes " << s << '\n';
}
int main()
{
using FuncType = std::function<void(std::string&)>;
std::list<std::pair<int, FuncType>> events =
{
{1, std::bind(tes, "1")},
{2, std::bind(tes2, "2")},
{3, std::bind(tes3, "3")} };
int t = 1;
auto remove_func = [&t](std::pair<int, FuncType> pair)
-> bool
{
return pair.first == t;
};
events.remove_if(remove_func);
for (auto ev : events)
{
std::cout << ev.first << ' ' ;
ev.second;
}
}
the result just display ev.first, but not the ev.second. what happened??
how to resolve this problem?? i mean display the string in FuncType function
such "2" and "3". or fixed this code properly to work to display each.
There are a couple of issues in the posted code
// ...
void tes(std::string s)
{ // ^^^^^^^^^^^^^
}
// ...
using FuncType = std::function<void(std::string&)>;
// ^^^^^^^^^^^^
std::list<std::pair<int, FuncType>> events =
{
{1, std::bind(tes, "1")},
{2, std::bind(tes2, "2")},
{3, std::bind(tes3, "3")}
// ^^^^^^^^^^^^^^^^^^^^
};
The functions like tes have one parameter of type std::string, the alias FuncType is a std::function with one parameter of type std::string&, but the pairs in events are assigned the results of std::bind, which have zero parameters (they are, well, binded).
Moreover, in the printing loop
for (auto ev : events)
{
std::cout << ev.first << ' ' ;
ev.second; // <- This does nothing, it should be a call.
}
The fix1 is straightforward:
using FuncType = std::function<void(void)>;
// ^^^^^^
// ...
for (auto ev : events)
{
std::cout << ev.first << ' ' ;
ev.second();
// ^^
}
1) https://godbolt.org/z/5f8srj9va
Fix the misprint:
std::cout << ev.first << ' ' << ev.second;
Related
I switched from c to c++ recently and just can't figure out what I'm doing wrong here.
I would like to access and set the member of a map via another function.
Here is my example which you can just copy to cpp.sh or so if you like
#include <iostream>
#include <map>
using namespace std;
struct test{
int i;
int j;
};
void addValues(test* val){
if (val == NULL){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
void printVal(test* val){
cout<<"finish " << val->i << " " << val->j;
}
int main()
{
map<string, test*> bla = {{"test1",NULL}};
addValues(bla.at("test1"));
printVal(bla.at("test1"));
return 0;
}
code from my project is a little bit more complex but it's basically this problem. I created a test in addValues() and have not deleted it. Why am I not able to print this value in printVal()? What am I missing?
Thanks in advance!
Parameters are passed by value. Pointers are no exception to that. Your addValues modifies a local copy of the pointer when a nullptr is passed. Modifying that local copy does not affect the pointer in the map. Pass the pointer by reference:
void addValues(test*& val){
if (val == nullptr){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
Or better yet, do not use raw pointers in the first place. Moreover, consider to write a constructor that initializes the members of test instead of relying on the caller to initialize them.
Example :
#include <iostream>
#include <map>
//using namespace std; NO teach yourself not to do this.
struct test
{
int i = 0; // <== in c++ you can initialize values of structs
int j = 0;
};
// this instead of printVal
std::ostream& operator<<(std::ostream& os, const test& t)
{
os << "i = " << t.i << ", j = " << t.j << "\n";
return os;
}
int main()
{
std::map<std::string, test> map =
{
{"test1",{1,1}},
{"test2",{2,2}},
};
// loop over all entries in the map
// range based for loop.
// each entry in the map is a key,value pair (not they key, not the value but a pair)
// https://en.cppreference.com/w/cpp/language/range-for
std::cout << "range based for over keyvalue pairs\n";
for (const auto& kv : map)
{
// note kv.second is where we use operator<< from earlier.
std::cout << "Key : " << kv.first << ", value : " << kv.second << "\n";
}
std::cout << "\n";
// structured bindings make code more readable
// https://en.cppreference.com/w/cpp/language/structured_binding
std::cout << "range based for using structured bindings \n";
for (const auto& [key, value] : map)
{
std::cout << "Key : " << key << ", value : " << value <<"\n";
}
std::cout << "\n";
return 0;
}
The system is able to figure out the type of each element using a.type().name() but seriously is not able to print them?
#include <iostream>
#include <vector>
#include <any>
#include <string>
#include <algorithm>
template<typename Last>
void addElement(std::vector<std::any>& container, Last last) {
std::cout << "Last = " << last << std::endl;
container.push_back(last);
}
template<typename First, typename... Rest>
void addElement(std::vector<std::any>& container, First first, Rest... rest) {
std::cout << "Elem = " << first << std::endl;
container.push_back(first);
addElement(container, rest...);
}
template<typename... Ts>
std::vector<std::any> createAnyVector(Ts... ts) {
std::vector<std::any> container;
addElement(container, ts...);
return container;
}
int main() {
std::cout << "ANYVECTOR" << std::endl;
std::vector<std::any> container = createAnyVector("Hello", 3.14, 'A', true, 42);
std::cout << "Number of elements in container = " << container.size() << std::endl; // 5 correct.
for (const auto& a : container) {
std::cout << a.type().name() << ", " << "HERE?" << std::endl;
}
}
If I just write a at the place where now HERE? stands, it returns the error:
No operator << matches these operands
operand types are: std::basic_ostream<char, std::char_traits<char>> << const << std::any
As the comments point out, you cannot do anything directly with std::any, you can just hold them.
If you control the API and have the option to create a wrapper around std::any, you can maintain a function pointer to print the current std::any's contents like so:
struct printable_any {
template <class T>
printable_any(T&& t) : m_val(std::forward<T>(t)) {
m_print_fn = [](std::ostream& os, const std::any& val) {
os << std::any_cast<std::decay_t<T>>(val);
};
}
private:
using print_fn_t = void(*)(std::ostream&, const std::any&);
std::any m_val;
print_fn_t m_print_fn;
friend std::ostream& operator<<(std::ostream& os, const printable_any& val) {
val.m_print_fn(os, val.m_val);
return os;
}
};
Note that even with this, you cannot take a random std::any and print it, you have to construct it yourself along with the function pointer.
Usage:
int main() {
std::vector<printable_any> vals {
"Hello", 3.14, 'A', true, 42
};
for (auto& v : vals) {
std::cout << v << '\n';
}
}
Prints
Hello
3.14
A
1
42
https://godbolt.org/z/o1sejrv1e
Well, what would this print:
struct Foo {
void *p;
};
any v = Foo{};
cout << v << '\n'; // what should this print?
There is no toString equivalent in C++. If you want that behavior, you may create your own hierarchy:
struct Printable {
virtual void print(ostream&) const = 0;
};
auto& operator<<(ostream& os, any const& obj) {
any_cast<Printable const&>(obj).print(os);
return os;
}
Or customize it as you wish and handle the error cases as you like, also add special cases for the integer types if you want, etc.
Does the vector have to be of type any or are you allowed to at least specify the kind of types that are stored in the vector? Because if you can at least specify which types are allowed, I recommend using std::variant.
example: std::vector<variant<int, string>> myVectorVariant;
After that, you can actually print to the console the items in your vector through the use of std::get_if from std::variant. copy-able function below to output your vector for the most of the main primitive types: int, float, char, string.
#include <variant>
#include <vector>
#include <iostream>
using namespace std;
void printVectorVariantValues(vector<variant<int, float, char, string>> arg) {
try {
for (auto val : arg) {
if (const auto intPtr (get_if<int>(&val)); intPtr)
cout << *intPtr << " ";
else if (const auto floatPtr (get_if<float>(&val)); floatPtr)
cout << *floatPtr << " ";
else if (const auto charPtr (get_if<char>(&val)); charPtr)
cout << *charPtr << " ";
else if (const auto stringPtr (get_if<string>(&val)); stringPtr)
cout << *stringPtr << " ";
}
} catch (bad_variant_access err) {
cout << "something" << " ";
}
cout << "DONE" << endl;
}
int main() {
vector<variant<int, float, char, string>> myVectorVariant = {1, 2, 'a', 'b', 3, 0.4f, 0.5f, "c", "DeF", 0.6f, "gHi", "JkL" };
printVectorVariantValues(myVectorVariant);
return 0;
}
/*
output below:
1 2 a b 3 0.4 0.5 c DeF 0.6 gHi JkL DONE
*/
I want to save and access at runtime the types and default values of inputs and outputs of a function.
I have some structs to hold what I need for now in FunDeclaration and FunParam and an example function foo to reflect. Live code here: https://onlinegdb.com/BySyS8f7D
Here the full source:
#include <iostream>
#include <string>
#include <unordered_map>
#include <any>
struct FunParam {
// This will be a custom identifier (string for now) "int", "string", etc...
std::string type;
// Default value for that parameter
std::any default_value;
};
struct FunDeclaration {
// Function input params
std::unordered_map<std::string, FunParam> ins;
// Function output params
std::unordered_map<std::string, FunParam> outs;
};
using FunctionsMap = std::unordered_map<std::string, FunDeclaration>;
void print(FunctionsMap &fmap) {
auto printParam = [](FunParam& p) {
if (p.type == "int") {
std::cout << "type: " << p.type << " default_value: " << std::any_cast<int>(p.default_value);
} else if (p.type == "double") {
std::cout << "type: " << p.type << " default_value: " << std::any_cast<double>(p.default_value);
} else if (p.type == "float") {
std::cout << "type: " << p.type << " default_value: " << std::any_cast<float>(p.default_value);
} else if (p.type == "std::string") {
std::cout << "type: " << p.type << " default_value: " << std::any_cast<std::string>(p.default_value);
}
};
for (auto& f : fmap) {
std::cout << "Fun: " << f.first << std::endl;
for (auto& in: f.second.ins) {
std::cout << "\t[in] name: " << in.first << " ";
printParam(in.second);
std::cout << std::endl;
}
for (auto& in : f.second.outs) {
std::cout << "\t[out] name: " << in.first << " ";
printParam(in.second);
std::cout << std::endl;
}
}
}
// Just an example function to work with, multiple inputs (default values), and multiple outputs
std::tuple<double, float> foo(int a = 10, std::string b = "HelloWorld") {
return { a * 10.0, b.size() };
}
int main() {
FunctionsMap gFuns;
gFuns["foo"].ins =
{
{"a", {"int", std::any(int(10))} },
{"b", {"std::string", std::any(std::string("HelloWorld"))} }
};
gFuns["foo"].outs = {
{"out0", {"double", std::any(double())} },
{"out1", {"float", std::any(float())} }
};
print(gFuns);
return 1;
}
How would you define a macro that spits this glue code(suppose gFuns is a global), and with multiple inputs/outputs? Is this possible with just one macro? Or I have to make a macro to each possibility of in/out param numbers?
gFuns["foo"].ins =
{
{"a", {"int", std::any(int(10))} },
{"b", {"std::string", std::any(std::string("HelloWorld"))} }
};
gFuns["foo"].outs = {
{"out0", {"double", std::any(double())} },
{"out1", {"float", std::any(float())} }
};
I was thinking about something like this:
#define ADD_FUN_DECL(name, in_types, in_defaultvalues, out_types, out_defaultvalues)
I was thinking about something like this:
I would group default value close with the type. I noticed that both paths - for input and outputs values - are similar, so I merged them together, as they only seem to differ with default value.
The following code could be enough to get you started. For more arguments, make sure to research how to overload macro on number of arguments. Note how HANDLE_PARAMS instuff is expanding the macro because instuff contains (....) brackets. The same happens in HANDLE_GENERIC. This is a trick for creating "lists of lists" in preprocessor.
#define HANDLE_GENERIC(type, name, ...) \
{ #name, { #type, std::any(type(__VA_ARGS__)) } }
// Overloading the macro on more number of arguments left to the reader.
#define HANDLE_PARAMS_2(a, b) HANDLE_GENERIC a , HANDLE_GENERIC b
#define HANDLE_PARAMS_N(_2,_1,N,...) HANDLE_PARAMS##N
#define HANDLE_PARAMS(...) HANDLE_PARAMS_N(__VA_ARGS__,_2,_1)(__VA_ARGS__)
#define ADD_FUN_DECL(name, instuff, outstuff) \
gFuns[#name].ins = { \
HANDLE_PARAMS instuff \
}; \
gFuns[#name].outs = { \
HANDLE_PARAMS outstuff \
}; \
ADD_FUN_DECL(
// the name of the struct
foo,
// a () list of (type, variablename, defaultvalue) for input values
(
(int, a, 10),
(std::string, b, "HelloWorld")
),
// a () list of (type, variablename) for output values
(
(double, out0),
(float, out1)
)
)
The code above results in the following:
gFuns["foo"].ins = { { "a", { "int", std::any(int(10)) } } , { "b", { "std::string", std::any(std::string("HelloWorld")) } } }; gFuns["foo"].outs = { { "out0", { "double", std::any(double()) } } , { "out1", { "float", std::any(float()) } } };
I'm learning C++ so my question might seem a bit stupid. I wanted to build a function that print every element in a vector. I come up with that but it seems to display the address of every element. I google it and find a nice solution but i wanted to do it this way so if anyone can explain me where i'm doing something wrong.
My code :
void display_vector(std::vector<int>& to_display);
int main()
{
std::vector<int> vector_to_sort = { 2,6,7,2,1,80,2,59,8,9 };
display_vector(vector_to_sort);
}
void display_vector(std::vector<int> &to_display)
{
for (int i = 0; i < to_display.size(); i++)
{
std::cout << to_display[i] << ', ';
}
std::cout << '\n';
}
The solution i found on internet :
#include <iterator>
void display_vector(const vector<int> &v)
{
std::copy(v.begin(), v.end(),
std::ostream_iterator<int>(std::cout, " "));
}
Output of my code :
21129661129671129621129611129680112962112965911296811296911296
You use ", " instead of ', '.
You can use any of the following print mechanism in the display() function:
void display_vector(std::vector<int> &to_display)
{
//by using Normal for loop
for (auto i = to_display.begin(); i != to_display.end(); ++i) {
cout << *i << " ";
}
cout << endl;
//by using Range based for loop
for (int & i : to_display) {
cout << i << " ";
}
std::cout << '\n';
}
In this statement
std::cout << to_display[i] << ', ';
^^^^^^
you are using a multybyte character literal that has an implementation defined value.
Substitute it for string literal ", ".
As for the function then for starters if the vector is not being changed in the function then the parameter should be a constant reference.
You can use the range-based for loop to outfput elements of the vector like for example
#include <iostream>
#include <vector>
std::ostream & display_vector( const std::vector<int> &to_display, std::ostream &os = std::cout );
int main()
{
std::vector<int> vector_to_sort = { 2,6,7,2,1,80,2,59,8,9 };
display_vector(vector_to_sort) << '\n';
}
std::ostream & display_vector( const std::vector<int> &to_display, std::ostream &os )
{
for ( const auto &item : to_display )
{
os << item << ", ";
}
return os;
}
Using such a function you can for example output the vector in a text file.
Just replace below line
std::cout << to_display[i] << ', ';
with
std::cout << to_display[i] << ", ";
Also note that if you just want to display vector in function then declare parameter as const reference as shown below
void display_vector(const std::vector<int> &to_display);
The debuggers make it easy to examine vectors but I include a simple template to print out vectors of standard types and often use it when debugging data that I wish to look at with other tools.
template<class T>
void print(const std::vector<T>& v){
for (auto x: v)
std::cout << x << std::endl;
}
I want to share structured data between C++ and Python languages using MessagePack like this one:
{
"t" : [ [t00,...,t0N], ... , [tM0,...,tMN] ],
"x" : [ x0,..,xN],
"P" : [ [P00, ..., P0N], ..., [PM0,...,PMN] ]
}
The number of variables is optional so in some cases I will have for example only:
{
"t" : [ [t00,...,t0N], ... , [tM0,...,tMN] ]
}
Decoding this in Python is pretty simple, my problem is to figure out
how to decode this in C++ if I don't know in advance the structure of
the data ? or the exact number of variables that I would have; is it
possible to iterate the structure in these cases?
I managed to handle a "fixed" data structure ( always with the same
number of variables ) defining a struct for example:
struct variables
{
std::vector< std::vector<double> > t;
std::vector< double > x;
std::vector< std::vector<double> > P;
MSPACK_DEFINE_MAP( t, x, P );
};
std::stringstream inBuffer;
.... (read data )
std::string str( inBuffer.str() );
msgpack::object_handle oh = msgpack::unpack( str.data(), str.size() );
msgpack::object deserialized = oh.get();
variables var;
deserialized.convert( var );
Is there a better way to accomplish this ?, how could manage optional
variables that could not appear in the structure ?; I repeat the
previous question: could I iterate an unknown data structure in C++?,
how ?
Thanks in advance!
Regards, Ernesto
There are two ways to treat unknown data structure.
The first way is using parse/visitor mechanism.
Here is an example:
#include <msgpack.hpp>
#include <sstream>
#include <iostream>
// This is a simple print example visitor.
// You can do any processing in your visitor.
struct my_visitor : msgpack::null_visitor {
bool start_map_key() {
processing_map_key = true;
return true;
}
bool end_map_key() {
processing_map_key = false;
return true;
}
bool start_array(uint32_t size) {
std::cout << "array (size:" << size << ")[" << std::endl;
return true;
}
bool end_array() {
std::cout << "]" << std::endl;
return true;
}
bool visit_str(const char* v, uint32_t size) {
if (processing_map_key) {
std::cout << "map key:" << std::string(v, size) << std::endl;
}
return true;
}
bool visit_positive_integer(uint64_t v) {
std::cout << "found value:" << v << std::endl;
return true;
}
bool processing_map_key = false;
std::string indent;
};
int main() {
// create test data
std::stringstream ss;
msgpack::packer<std::stringstream> pk(ss);
pk.pack_map(1);
pk.pack("t");
pk.pack_array(2);
pk.pack_array(3);
pk.pack(1);
pk.pack(2);
pk.pack(3);
pk.pack_array(3);
pk.pack(4);
pk.pack(5);
pk.pack(6);
// print data (for debug)
{
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
std::cout << oh.get() << std::endl;
}
// apply visitor
{
my_visitor mv;
msgpack::parse(ss.str().data(), ss.str().size(), mv);
}
}
Running demo: https://wandbox.org/permlink/3NrR4IMDIuLTk9e9
See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_visitor.
The other way is using msgpack::type::variant or `msgpack::type::variant_ref.
The former copies data, you can update it. The latter doesn't copy data. You cannot update it.
This approach requires boost. So you need to define MSGPACK_USE_BOOST. I recommend defining as a compiler option.
// Boost is required
#define MSGPACK_USE_BOOST
#include <msgpack.hpp>
#include <sstream>
#include <iostream>
struct my_visitor:boost::static_visitor<void> {
void operator()(uint64_t v) const {
std::cout << "positive insteger:" << v << std::endl;
}
// const is required for map key because std::multimap's key (first) is const.
void operator()(std::string const& v) const {
std::cout << "string:" << v << std::endl;
}
void operator()(std::vector<msgpack::type::variant>& v) const {
std::cout << "array found" << std::endl;
for (auto& e : v) {
boost::apply_visitor(*this, e);
}
}
void operator()(std::multimap<msgpack::type::variant, msgpack::type::variant>& v) const {
std::cout << "map found" << std::endl;
for (auto& e : v) {
std::cout << "key:" << std::endl;
boost::apply_visitor(*this, e.first);
std::cout << "value:" << std::endl;
boost::apply_visitor(*this, e.second);
}
}
template <typename T>
void operator()(T const&) const {
std::cout << " match others" << std::endl;
}
};
int main() {
// create test data
std::stringstream ss;
msgpack::packer<std::stringstream> pk(ss);
pk.pack_map(1);
pk.pack("t");
pk.pack_array(2);
pk.pack_array(3);
pk.pack(1);
pk.pack(2);
pk.pack(3);
pk.pack_array(3);
pk.pack(4);
pk.pack(5);
pk.pack(6);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
std::cout << oh.get() << std::endl;
msgpack::type::variant v = oh.get().as<msgpack::type::variant>();
boost::apply_visitor(my_visitor(), v);
}
Running demo: https://wandbox.org/permlink/HQwJjfwW8rLEMi0d
See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_variant
Here are exampless:
https://github.com/msgpack/msgpack-c/blob/master/example/boost/msgpack_variant_capitalize.cpp
https://github.com/msgpack/msgpack-c/blob/master/example/boost/msgpack_variant_mapbased.cpp
Both ways can treat unpredictable data structure. You need to do some visitor processing. If the data structure is predictable some extent, your original approach is also good way.
Actually there is a simpler way, if you are dealing with maps (like stated in the question), not arrays.
msgpack::object_handle oh = msgpack::unpack(/* some data */);
std::map<std::string,msgpack::type::variant> map = obj.convert();
This way you will get a map with all the data, no need for a visitor or boost.