Display vector contents

When displaying the contents of a vector is there a reason why print Works and cout does not work?

This works:
 
print(VectorName);


This makes gcc very unhappy:
 
cout << (VectorName) << endl;
Show me a (complete) program where
print(VectorName);
works.
You haven't shown the code for print((), but presumably it knows how to iterate through a vector and print the elements.

Also, you haven't shown the declaration for VectorName. I'm assuming it's a simple std:vector of some object. The std::vector class does not know how to cout itself. i.e. the std:vector claas has no << operator.
You can always write a << operator for a vector:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <vector>
using namespace std;


template<typename T> ostream & operator << ( ostream & out, const vector<T> &V )
{
   for ( T e : V ) out << e << ' ';
   return out;
}


int main()
{
   vector<int> A = { 10, 20, 30 };
   cout << A << '\n';
}


10 20 30


Last edited on
Print generic sequences (C++20):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <iterator>
#include <ranges> // C++20
#include <map>
#include <tuple>
#include <string>
#include <vector>
#include <tuple>
#include <list>
#include <variant>

static_assert( __cplusplus >= 202002L, "C++20 or later is required" ) ;

namespace print_utils
{
    // print generic range (declaration: members of pair/tuple/variant may be ranges)
    template < typename OSTREAM, std::ranges::range RANGE >
    OSTREAM& operator<<( OSTREAM& stm, const RANGE& seq ) ;

    // print std::pair (first:second)
    template < typename OSTREAM, typename FIRST, typename SECOND >
    OSTREAM& operator<<( OSTREAM& stm, const std::pair<FIRST,SECOND>& pair )
    { return stm << '(' << pair.first << ':' << pair.second << ')' ; }

    namespace detail
    {
        // std::tuple print helper (e1,e2,e3...)
        template < typename OSTREAM, typename TUPLE, std::size_t... INDEX >
        OSTREAM& print( OSTREAM& stm, const TUPLE& tuple, std::index_sequence<INDEX...> )
        {
            stm << '(' ;
            ( ... , ( stm << ( INDEX == 0 ? "" : "," ) << std::get<INDEX>(tuple) ) ) ;
            return stm << ')' ;
        }

    }

    // print std::tuple
    template < typename OSTREAM, typename... T >
    OSTREAM& operator<<( OSTREAM& stm, const std::tuple<T...>& tuple )
    { return detail::print( stm, tuple, std::make_index_sequence< sizeof...(T) >() ) ; }

    // print std::variant
    template < typename OSTREAM, typename... T >
    OSTREAM& operator<<( OSTREAM& stm, const std::variant<T...>& variant )
    { return std::visit( [&] ( auto&& v ) -> OSTREAM& { return stm << v ; }, variant ) ; }

    // print generic range
    template < typename OSTREAM, std::ranges::range RANGE >
    OSTREAM& operator<<( OSTREAM& stm, const RANGE& seq )
    {
        stm << '[' << ' ' ;
        for( const auto& elt : seq ) stm << elt << ' ' ;
        return stm << ']' ;
    }
}

int main()
{
    using namespace print_utils ; // required

    int arr[][5] { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8, 9 } };
    std::cout << "2d array: " << arr << '\n' ;
    std::wcout << L"2d array: " << arr << L'\n' ;

    const std::map< int, std::string > map { { 0, "zero" }, { 1, "one" }, { 2, "two" } } ;
    std::cout << "map: " << map << '\n' ;

    std::vector vec { map, map } ;
    vec.back().emplace( 3, "three" ) ;
    std::cout << "vector of maps: " << vec << '\n' ;

    struct abc
    {
        auto begin() const noexcept { return "abcdefghijklmnpqrstuvwxyz" ; }
        auto end() const noexcept { return begin() + std::clamp( width, 0, 26 ) ; }
        int width = 6 ;
    };
    const abc chars{6} ;
    std::cout << "a custom range: " << chars << '\n' ;

    std::tuple< int, const char*, double, abc > tup { 12, "four", 4.5, {4} } ;
    std::cout << "tuple: " << tup << '\n' ;

    std::list< decltype(tup) > lst { tup, tup, tup } ;
    std::wcout << L"list of tuples: " << lst << L'\n' ;

    using var_t = std::variant< int, const char*, double, abc, decltype(map) > ;
    std::vector<var_t> vecv { var_t(12), var_t("five"), var_t(4.5), var_t( abc{5} ), var_t(map), var_t("six") } ;
    std::cout << "vector of variants: " << vecv << '\n' ;
}

http://coliru.stacked-crooked.com/a/8a336dc8f95a26d0
Note L12. For MSVS, the default value returned for __cplusplus is 199711L. To get the correct value you have to add /Zc:__cplusplus as a command line option, starting with VS2017. Also note that 201103L isn't supported and won't be returned.

199711L(until C++11),
[201103L(C++11) - not supported with MSVS]
201402L(C++14)
201703L(C++17)
202002L(C++20)

Also, don't do an equality test (use a >= test like used above). My version of MSVS 2022 preview currently reports 202004 !
Last edited on
> Also, don't do an equality test.

__cplusplus >= 202002L is not an equality test; the check is for greater than or equal
@JL Borges. I didn't mean to imply that your code was wrong. It isn't. I was intending to suggest in general that an equality test shouldn't be used and that a >= test should be used - like you did. Sorry for any non-intended implication re your code for my poor wording. I've changed my wording above to make this clear.
Last edited on
> I was intending to suggest in general that an equality test shouldn't be used and that a >= test should be used

An equality test should be used if the intent is to check for a match with a specific version of the standard.

A greater than or equal check is usually done under the expectation that a future revision of the standard (which will define a greater value for __cplusplus) would, by and large, be backward-compatible with C++20; not because a compiler vendor (like Microsoft in this case) might do something perverse.
Topic archived. No new replies allowed.