This question already has answers here:
Printing a `vector<pair<int, int>>`
(4 answers)
Closed 8 months ago.
#include <iostream>
#include <utility>
#include <vector>
int main() {
std::vector<std::pair<int,int>> v;
v.push_back({10,20});
// This works
std::cout << v[0].first << " " << v[0].second << "\n";
// But I'd like to just be able to do
std::cout << v[0] << "\n";
}
How can we print a vector of pairs instead of printing separate values of the pairs like v[i].first and v[i].second? I want to print like cout << v[i]; but it shows an error.
std::pair does not have a defined operator<<. Therefore, you have to define it yourself.
You can use this template to print any std::pair<T, Y> you want, as long as T and Y have defined operator<< as well:
#include <iostream>
#include <utility>
template<typename T, typename Y>
auto operator<<(std::ostream& stream, std::pair<T,Y> const& p) -> std::ostream& {
stream << p.first << ' ' << p.second;
return stream;
}
auto main() -> int {
std::pair<int,int> p{1, 2};
std::cout << p << '\n';
}
Related
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 have a variable x.
It may either be of type char, uint8_t or std::string.
I wish to output the number (not character), using the same expression involving std::cout. This is because I use this expression in generated code.
At code-generation-time, I currently don't know if x will be char, uint8_t or std::string.
std::cout << x << std::endl does not work if x is of type char, since it will output the character and not the number.
std::cout << +x << std::endl does not work if x is of type std::string.
std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? +x : x) << std::endl does not work if x is of type std::string.
std::cout << (typeid(x) == typeid(uint8_t) || typeid(x) == typeid(char) ? static_cast<int>(x) : x) << std::endl does not work if x is of type std::string.
I am aware that std::cout can be configured in various ways by piping std::hex or std::boolalpha, but I know of no possible way to configure std::cout to output a char as a number, without casting the char first.
Is there a way to use reflection, operator overloading, templates or something else
so that one can have a single unified statement for outputting x, as a number?
For example, if x is 65 with type char, the desired output is 65, not A.
Just format a helper and specialize the versions you want to customize appropriately. For example:
#include <iostream>
template <typename T>
struct formatter {
T const& value;
};
template <typename T>
formatter<T> format(T const& value) {
return formatter<T>{value};
}
template <typename T>
std::ostream& operator<< (std::ostream& out, formatter<T> const& v) {
return out << v.value;
}
std::ostream& operator<< (std::ostream& out, formatter<char> const& v) {
return out << int(v.value);
}
template <std::size_t N>
std::ostream& operator<< (std::ostream& out, formatter<char[N]> const& v) {
return out << '\'' << v.value << '\'';
}
int main() {
std::cout << "char=" << format('c') << " "
<< "int=" << format(17) << " "
<< "string=" << format("foo") << " "
<< "\n";
}
I guess you are working within generic context. So your basic problem is that you need static dispatch. The trigraph operator ? : does not provide this. it is evaluated at run time and will always invoke the same operator<<.
So you have two options:
use a helper class with partial specialization.
use static if. I.e.:
if constexpr (std::is_integral<decltype(x)>::value)
std::cout << static_cast<int>(x) << std::endl;
else
std::cout << x << std::endl;
The latter requires C++17.
This solution worked for me. It outputs the char as a number by using the output function together with template specialization and if constexpr:
#include <cstdint>
#include <iostream>
#include <string>
using namespace std::string_literals;
template <typename T> void output(std::ostream& out, T x)
{
if constexpr (std::is_integral<decltype(x)>::value) {
out << static_cast<int>(x);
} else {
out << x;
}
}
int main()
{
char x = 65;
uint8_t y = 66;
std::string z = "hi"s;
// output: A
std::cout << x << std::endl;
// output: 65
output(std::cout, x);
std::cout << std::endl;
// output: B
std::cout << y << std::endl;
// output: 66
output(std::cout, y);
std::cout << std::endl;
// output: "hi"
output(std::cout, z);
std::cout << std::endl;
return 0;
}
Thanks to Dietmar Kühl and Marcel for the helpful answers.
This question already has answers here:
How do I print out the contents of a vector?
(31 answers)
Closed 4 years ago.
I am trying to print a vector of integers to the terminal using "cout", but I get an error message during compiling:
no match for 'operator<<' (operand types are 'std::basic_ostream' and 'std::vector')
cout << "Disparity at points: " << disparityVector << endl;
The snippet of code looks like this:
vector<int> disparityVector;
for ( int i=0; i<drawPixels.size(); i++) // Get disparity at each point of the drawn line
disparityVector.push_back((int)disparityMapOutput.at<int16_t>(pos[i].y, pos[i].x));
cout << "Disparity at points: " << disparityVector << endl;
There is no error with assigning the values to the vector, only the "cout" part of the code is making errors
For example, using ostream_iterator.
Sample from that page:
// ostream_iterator example
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
int main () {
std::vector<int> myvector;
for (int i=1; i<10; ++i) myvector.push_back(i*10);
std::ostream_iterator<int> out_it (std::cout,", ");
std::copy ( myvector.begin(), myvector.end(), out_it );
return 0;
}
You'll need something like below, if you want to do it the way you've coded it.
template<class T>
inline std::ostream& operator<< (std::ostream& o, std::vector<T> const& v) {
for (auto const& i : v)
o << i << " ";
return o;
}
std::ostream& operator<<(std::ostream& os, const vector<int>& v)
{
std::ostream_iterator<int> _oit(cout, " ");
std::copy(v.begin(), v.end(), _oit);
return os;
}
This error means that vector<T> has no operator<< implementation.
You need to iterate over your vector and print each element:
for(int i = 0; i < disparityVector.size; i++) {
cout << disparityVector[i];
}
cout << endl;
I'm asking myself if it is possible to extend boost-range by an adaptor, which I call adjacentAdaptor. This adaptor should basically iterate over all pairs of adjacent elements in a vector, list and so on.
I think this function is very useful in my use cases, where I often have to iterate over lists representing time steps.
The output of the last for loop should be something like:
0 1
1 2
2 3
A vector having only one element or no elements should produce nothing.
I tried using boost::adaptors::sliced producing the necessary sublist, but then I don't know how boost::range can help me to zip both subranges to one.
I just found a probable solution using boost::iterators, but I really don't like the amount of code one has to write. Also I'm missing the first and second instead I have to write a clumsy get<>. Unfortunately, the program crashes if the vector is empty!
#include <vector>
#include <iostream>
#include <boost/range.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>
int main()
{
std::vector<int> v = { 0,1,2,3 };
for (auto iter : v | boost::adaptors::sliced(0, v.size() - 1)) {
std::cout << "First: " << iter << std::endl;
}
for (auto iter : v | boost::adaptors::sliced(1, v.size())) {
std::cout << "Second: "<< iter << std::endl;
}
auto s = boost::iterators::make_zip_iterator(boost::make_tuple(v.begin(), v.begin() + 1));
auto e = boost::iterators::make_zip_iterator(boost::make_tuple(v.end()-1, v.end()));
for (auto iter : boost::make_iterator_range(s, e)) {
std::cout << iter.get<0>() << " " << iter.get<1>() << std::endl;
}
// for (auto iter : v | adjacentAdaptor) {
// std::cout << iter.first << " " << iter.second << std::endl;
// }
}
I'm very glad for any help I can receive in this question.
Own partial solution
After some template type deduction I came up with something relatively useable.
#include <vector>
#include <iostream>
#include <boost/range.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>
template<typename T>
using retHelperType = decltype(boost::iterators::make_zip_iterator(boost::make_tuple(T().begin(), T().begin() + 1)));
template<typename T>
using retType = decltype(boost::make_iterator_range(retHelperType<T>(), retHelperType<T>()));
template<typename T>
retType<T> adjacentIterator(T& v) {
if (v.empty()) {
auto s = boost::iterators::make_zip_iterator(boost::make_tuple(v.end(), v.end()));
auto e = boost::iterators::make_zip_iterator(boost::make_tuple(v.end(), v.end()));
return boost::make_iterator_range(s, e);
}
else {
auto s = boost::iterators::make_zip_iterator(boost::make_tuple(v.begin(), std::next(v.begin())));
auto e = boost::iterators::make_zip_iterator(boost::make_tuple(std::prev(v.end()), v.end()));
return boost::make_iterator_range(s, e);
}
}
int main()
{
retType<std::vector<int>> x;
std::vector<int> v = { };
for (auto iter : adjacentIterator(v)) {
std::cout << iter.get<0>() << " " << iter.get<1>() << std::endl;
}
}
Still, it would be nicer to access the elements with first and second, but I have no idea to achieve this behavior.
I have this code that works already:
// mem_fun example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <map>
using namespace std;
struct C
{
C(int i): y_(i) {};
int y_;
string op1(int x)
{
std::ostringstream oss;
oss << "operation 1: " << x+y_;
return oss.str();
}
string op2(string x)
{
std::ostringstream oss;
oss << "operation 2: " << x << "+" << y_;
return oss.str();
}
};
struct container: map<string, C>
{
// doesn't compile
// void safeOperation(string key, ??? bound_function_and_arg_object )
template< typename argType >
void safeOperation(string key, string (C::*mf)(argType a), argType a)
{
iterator it = find(key);
if (it != end())
{
C* pC = &(it->second);
cout << (pC->*mf)(a) << "\n";
}
else
{
cout << "key: " << key << " missing\n";
}
}
};
int main () {
container objects;
objects.insert(container::value_type("a1", C(1)));
objects.insert(container::value_type("b2", C(2)));
objects.insert(container::value_type("c3", C(3)));
objects.safeOperation("a1", &C::op1, 1);
objects.safeOperation("b2", &C::op1, 2);
objects.safeOperation("d4", &C::op1, 4);
objects.safeOperation("c3", &C::op2, string("3"));
return 0;
}
I'd like to change the template function on the map to use std::mem_fun and to bind the parameters together with the operation, rather than specify them as separate parameters to safeOperation.
In other words, I'd prefer to call safeOperation similar to this:
// wrong, but hopefully communicates what I'm trying to do:
objects.safeOperation(someKey, bind(&C::op1, 4));
The sample code is here: http://cpp.sh/74pgb
I'm probably missing something simple, but appreciate the help.
When you bind a member function, the first argument has to be an instance of the class whose member function it is. So what you want to do is generalize safeOperation to take any function that can be called on a C*:
template< typename F >
void safeOperation(string key, F func) {
iterator it = find(key);
if (it != end())
{
C* pC = &(it->second);
cout << func(pC) << "\n";
}
else
{
cout << "key: " << key << " missing\n";
}
}
And then generate your funcs by binding with the argument, but also leaving a placeholder:
using namespace std:;placeholders;
objects.safeOperation("a1", std::bind(&C::op1, _1, 1));
// ^^
// placeholder for pC
boost/std::bind create an object with an implementation-specific type. The only requirement is that the object is callable using operator().
To handle any functional objects you can change your function template in the following way:
template< typename F >
void safeOperation(string key, F f)
{
// ...
cout << f(pC) << "\n";
// ...
objects.safeOperation("someKey", bind(&C::op1, placeholders::_1, 4));
That should enable almost the syntax you require.