C++ stream insertion overloading error - c++

I'm having trouble with a basic stream insertion overload. The code is fairly self-explanatory:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
class dictionary
{
public:
using map_type = std::map<std::string, std::string>;
using ostream_iterator_type = std::ostream_iterator<map_type::value_type>;
private:
map_type inner;
public:
dictionary() : inner()
{
inner["foo"] = "lorem";
inner["baz"] = "ipsum";
}
void
write(std::ostream& os)
{
os << "{\n";
std::copy(std::begin(inner), std::end(inner), ostream_iterator_type(os, "\n"));
os << "}";
}
};
dictionary::ostream_iterator_type::ostream_type&
operator<<(dictionary::ostream_iterator_type::ostream_type& os,
dictionary::map_type::value_type const& p)
{
os << p.first << " => " << p.second;
return os;
}
This code throws some huge template errors, claiming that there's no appropriate overload for operator<< with the two arguments that I've clearly defined. What obvious problem am I missing?
Thanks!

The first thing I've noticed is the lack of <ostream> and <algorithm> includes. Also you seem to define operator << only after it is required. But the real problem is that you are trying to define operator << taking ::std::pair as second parameter outside of std namespace. You can fix it appropriately redefining it like this:
#include <iterator>
#include <map>
#include <string>
#include <ostream>
#include <algorithm>
class dictionary
{
public:
using map_type = std::map<std::string, std::string>;
private:
map_type inner;
public:
dictionary() : inner()
{
inner["foo"] = "lorem";
inner["baz"] = "ipsum";
}
void
write(std::ostream& os);
};
namespace std
{
std::ostream &
operator <<(std::ostream & os, dictionary::map_type::const_reference & p)
{
os << p.first << " => " << p.second;
return os;
}
} // namespace std
void dictionary::
write(std::ostream& os)
{
using ostream_iterator_type = std::ostream_iterator<map_type::value_type>;
os << "{\n";
std::copy(std::begin(inner), std::end(inner), ostream_iterator_type(os, "\n"));
os << "}";
}

Related

How to serialize and deserialize a hash in Redis (using redis-cpp library)

I'm using Redis with C++, so I'm using redis-cpp library to use it with this language. I'm trying to understand RESP protocol. As far as I know, this protocol can serialize and deserialize simple strings, errors, integers, bulk strings and arrays. I want to serialize and deserialize hash too, so I was trying to implement the code but is not as easy as I tough. This library implments some examples, so I was just trying to modify one of these examples:
Here is where data is called:
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <redis-cpp/execute.h>
namespace resps = rediscpp::resp::serialization;
namespace respds = rediscpp::resp::deserialization;
auto make_sample_data()
{
std::ostringstream stream;
put(stream, resps::array{
resps::simple_string{"This is a simple string."},
resps::error_message{"This is an error message."},
resps::bulk_string{"This is a bulk string."},
resps::integer{100500},
resps::array{
resps::simple_string("This is a simple string in a nested array."),
resps::bulk_string("This is a bulk string in a nested array.")
}
});
return stream.str();
}
I want to add a line similar to the others like: resps::hash(-add here an string, an integer, etc-)
And main function looks like this:
{
try
{
auto const data = make_sample_data();
std::cout << "------------ Serialization ------------" << std::endl;
std::cout << data << std::endl;
std::cout << "------------ Deserialization ------------" << std::endl;
std::istringstream stream{data};
print_sample_data(stream, std::cout);
std::cout << std::endl;
}
catch (std::exception const &e)
{
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Serialization function of simple_string, for example, is build like this:
#ifndef REDISCPP_RESP_SERIALIZATION_H_
#define REDISCPP_RESP_SERIALIZATION_H_
// STD
#include <cstdint>
#include <forward_list>
#include <ostream>
#include <string_view>
#include <type_traits>
#include <tuple>
#include <utility>
// REDIS-CPP
#include <redis-cpp/detail/config.h>
#include <redis-cpp/resp/detail/marker.h>
#include <redis-cpp/resp/detail/overloaded.h>
namespace rediscpp
{
inline namespace resp
{
namespace serialization
{
template <typename T>
void put(std::ostream &stream, T &&value)
{
value.put(stream);
}
class simple_string final
{
public:
simple_string(std::string_view value) noexcept
: value_{std::move(value)}
{
}
void put(std::ostream &stream)
{
stream << detail::marker::simple_string
<< value_
<< detail::marker::cr
<< detail::marker::lf;
}
private:
std::string_view value_;
};
And deserialization for same function is build like this:
#ifndef REDISCPP_RESP_DESERIALIZATION_H_
#define REDISCPP_RESP_DESERIALIZATION_H_
// STD
#include <cstdint>
#include <istream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
// REDIS-CPP
#include <redis-cpp/detail/config.h>
#include <redis-cpp/resp/detail/marker.h>
namespace rediscpp
{
inline namespace resp
{
namespace deserialization
{
[[nodiscard]]
auto get_mark(std::istream &stream)
{
switch (stream.get())
{
case detail::marker::simple_string :
return detail::marker::simple_string;
case detail::marker::error_message :
return detail::marker::error_message;
case detail::marker::integer :
return detail::marker::integer;
case detail::marker::bulk_string :
return detail::marker::bulk_string;
case detail::marker::array :
return detail::marker::array;
default:
break;
}
throw std::invalid_argument{
"[rediscpp::resp::deserialization::get_mark] "
"Bad input format."
};
}
template <typename T>
[[nodiscard]]
T get(std::istream &stream)
{
return {stream};
}
class simple_string final
{
public:
simple_string(std::istream &stream)
{
std::getline(stream, value_);
value_.pop_back(); // removing '\r' from string
}
[[nodiscard]]
std::string_view get() const noexcept
{
return value_;
}
private:
std::string value_;
};
How can I add hash as a type and build the functions in serialize and deserialize as it was done with simple_string? Thanks in advance!!

std::variant cout in C++

I am relatively new to CPP and have recently stumbled upon std::variant for C++17.
However, I am unable to use the << operator on such type of data.
Considering
#include <iostream>
#include <variant>
#include <string>
using namespace std;
int main() {
variant<int, string> a = "Hello";
cout<<a;
}
I am unable to print the output. Is there any short way of doing this? Thank you so much in advance.
You can use std::visit if you don't want to use std::get.
#include <iostream>
#include <variant>
struct make_string_functor {
std::string operator()(const std::string &x) const { return x; }
std::string operator()(int x) const { return std::to_string(x); }
};
int main() {
const std::variant<int, std::string> v = "hello";
// option 1
std::cout << std::visit(make_string_functor(), v) << "\n";
// option 2
std::visit([](const auto &x) { std::cout << x; }, v);
std::cout << "\n";
}
use std::get
#include <iostream>
#include <variant>
#include <string>
using namespace std;
int main() {
variant<int, string> a = "Hello";
cout << std::get<string>(a);
}
If you want to get automatically, it can't be done without knowing its type. Maybe you can try this.
string s = "Hello";
variant<int, string> a = s;
cout << std::get<decltype(s)>(a);
#include <iostream>
#include <variant>
#include <string>
int main( )
{
std::variant<int, std::string> variant = "Hello";
std::string string_1 = std::get<std::string>( variant ); // get value by type
std::string string_2 = std::get<1>( variant ); // get value by index
std::cout << string_1 << std::endl;
std::cout << string_2 << std::endl;
//may throw exception if index is specified wrong or type
//Throws std::bad_variant_access on errors
//there is also one way to take value std::visit
}
Here is the description link: https://en.cppreference.com/w/cpp/utility/variant

Problems with boost::multi_index, incomplete type, no matching function call, etc

This is with Boost 1.72.0. What am I doing wrong? This is a simple example where I'm trying to create a struct named employee, which can be sorted by both id and name. I wanted to try this out before integrating multi_index into a larger more complex project, which requires a lot more indices. But I ran into errors using the code below. I compiled it using GCC 7.30. Since the error messages are complex and verbose, I left them off.
Here is the full source of the minimal example:
#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
using namespace boost::multi_index;
struct employee {
employee(unsigned int id, std::string name)
: id(id), name(name)
{}
unsigned int id;
std::string name;
bool operator<(const employee& other) const noexcept {
return this->id < other.id;
}
};
struct indexedById {};
struct indexedByName {};
using EmployeeContainer = boost::multi_index_container
<
employee,
indexed_by<
ordered_unique<tag<indexedById>, identity<employee>>,
hashed_non_unique<tag<indexedByName>, member<employee, std::string, &employee::name>>
>
>;
int main()
{
EmployeeContainer mi;
auto& inserter = mi.get<indexedByName>();
inserter.emplace(0, "uber duber");
inserter.emplace(1, "gotcha");
inserter.emplace(3, "dang");
for(auto& it : mi.get<indexedById>())
std::cout << it.id << ": " << it.name << std::endl;
std::cin.get();
return 0;
}
OK, I fixed it. I needed to include the header files and in addition to the others.
#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
using namespace boost::multi_index;
struct employee {
employee(unsigned int id, std::string name)
: id(id), name(name)
{}
unsigned int id;
std::string name;
bool operator<(const employee& other) const noexcept {
return this->id < other.id;
}
};
struct indexedById {};
struct indexedByName {};
using EmployeeContainer = boost::multi_index_container
<
employee,
indexed_by<
ordered_unique<tag<indexedById>, identity<employee>>,
hashed_non_unique<tag<indexedByName>, member<employee, std::string, &employee::name>>
>
>;
int main()
{
EmployeeContainer mi;
auto& inserter = mi.get<indexedByName>();
inserter.emplace(0, "uber duber");
inserter.emplace(1, "gotcha");
inserter.emplace(3, "dang");
for(auto& it : mi.get<indexedById>())
std::cout << it.id << ": " << it.name << std::endl;
std::cin.get();
return 0;
}
This is the output:
0: uber duber
1: gotcha
3: dang
So, moral of the story, add header files for each type of index you're doing!

C++ istream_iterator is not a member of std

Can anyone tell me why the below piece of code I wrote when compiling keeps complaining istream_iterator is not a member of std please can you tell?
Thanks guys
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <fstream>
//#include<sstream>
struct field_reader: std::ctype<char> {
field_reader(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(table_size, std::ctype_base::mask());
rc[';'] = std::ctype_base::space;
return &rc[0];
}
};
struct Stud{
double VehicleID;
double FinancialYear;
double VehicleType;
double Manufacturer;
double ConditionScore;
friend std::istream &operator>>(std::istream &is, Stud &s) {
return is >> s.VehicleID >> s.FinancialYear >> s.VehicleType >> s.Manufacturer >> s.ConditionScore;
}
// we'll also add an operator<< to support printing these out:
friend std::ostream &operator<<(std::ostream &os, Stud const &s) {
return os << s.VehicleID << "\t"
<< s.FinancialYear << "\t"
<< s.VehicleType << "\t"
<< s.Manufacturer << "\t"
<< s.ConditionScore;
}
};
int main(){
// Open the file:
std::ifstream in("VehicleData_cs2v_1.csv");
// Use the ctype facet we defined above to classify `;` as white-space:
in.imbue(std::locale(std::locale(), new field_reader));
// read all the data into the vector:
std::vector<Stud> studs{(std::istream_iterator<Stud>(in)),
std::istream_iterator<Stud>()};
// show what we read:
for (auto s : studs)
std::cout << s << "\n";
}
So please if you spot the issue let me know as I can't quite tell at the moment and I believe I put in all the necessary include libraries
The error message may sound a bit misleading, but it's the best thing the compiler could say. std::istream_iterator is declared in the <iterator> header file, that's what causes your problem.
Just add this to your includes
#include <iterator>

Defining << operator at a base class

I'm trying to define the << operator for a base class, so I can later print the identifier of each object easily.
I have tried an SSCCE, but I don't really know where the problem is, since I'm printing a direction and not the content. I don't know if the problem appears by printing the vector position, or by printing the std::string(char[]).
main.cpp:
#include "City.h"
#include <vector>
#include <iostream>
int main() {
std::vector<Location*> locations;
locations.push_back(new City("TEST"));
for(unsigned int it = 0; it<locations.size(); it++){
std::cout << locations[it] << std::endl;
}
return 0;
}
Location.h:
#include <cstring>
#include <string>
class Location {
public:
Location(const std::string id);
friend std::ostream& operator<<(std::ostream& os, Location& loc);
std::string GetId();
private:
// Name/identifier of the location
char ID[5];
};
Location.cpp:
#include "Location.h"
Location::Location(const std::string id){
memset(this->ID, 0, 5);
strncpy(this->ID, id.c_str(), 5); // I have it as a char[5] at a larger app
}
std::string Location::GetId(){
return std::string(this->ID);
}
std::ostream& operator<<(std::ostream& os, Location& loc){
os << loc.GetId();
return os;
}
City.h:
#include "Location.h"
class City: public Location{
public:
City(std::string id);
};
City.cpp:
#include "City.h"
City::City(const std::string id) : Location(id){
}
Any idea?