C++ 如何打印向量的内容?
如何将C++ 如何打印向量的内容?,c++,vector,output,stdvector,cout,C++,Vector,Output,Stdvector,Cout,如何将std::vector的内容打印到屏幕上 一个实现以下操作符的解决方案这里是一个工作库,作为一个完整的工作程序呈现,我刚刚拼凑在一起: #include <set> #include <vector> #include <iostream> #include <boost/utility/enable_if.hpp> // Default delimiters template <class C> struct Delims
std::vector
的内容打印到屏幕上
一个实现以下
操作符的解决方案这里是一个工作库,作为一个完整的工作程序呈现,我刚刚拼凑在一起:
#include <set>
#include <vector>
#include <iostream>
#include <boost/utility/enable_if.hpp>
// Default delimiters
template <class C> struct Delims { static const char *delim[3]; };
template <class C> const char *Delims<C>::delim[3]={"[", ", ", "]"};
// Special delimiters for sets.
template <typename T> struct Delims< std::set<T> > { static const char *delim[3]; };
template <typename T> const char *Delims< std::set<T> >::delim[3]={"{", ", ", "}"};
template <class C> struct IsContainer { enum { value = false }; };
template <typename T> struct IsContainer< std::vector<T> > { enum { value = true }; };
template <typename T> struct IsContainer< std::set<T> > { enum { value = true }; };
template <class C>
typename boost::enable_if<IsContainer<C>, std::ostream&>::type
operator<<(std::ostream & o, const C & x)
{
o << Delims<C>::delim[0];
for (typename C::const_iterator i = x.begin(); i != x.end(); ++i)
{
if (i != x.begin()) o << Delims<C>::delim[1];
o << *i;
}
o << Delims<C>::delim[2];
return o;
}
template <typename T> struct IsChar { enum { value = false }; };
template <> struct IsChar<char> { enum { value = true }; };
template <typename T, int N>
typename boost::disable_if<IsChar<T>, std::ostream&>::type
operator<<(std::ostream & o, const T (&x)[N])
{
o << "[";
for (int i = 0; i != N; ++i)
{
if (i) o << ",";
o << x[i];
}
o << "]";
return o;
}
int main()
{
std::vector<int> i;
i.push_back(23);
i.push_back(34);
std::set<std::string> j;
j.insert("hello");
j.insert("world");
double k[] = { 1.1, 2.2, M_PI, -1.0/123.0 };
std::cout << i << "\n" << j << "\n" << k << "\n";
}
#包括
#包括
#包括
#包括
//默认分隔符
模板结构Delims{static const char*delim[3];};
模板常量char*Delims::delim[3]={“[”,“,”,“]”};
//集合的特殊分隔符。
模板结构Delims{static const char*delim[3];};
模板常量char*Delims::delim[3]={{{{,“,”,“,”};
模板结构IsContainer{enum{value=false};};
模板结构IsContainer{enum{value=true};};
模板结构IsContainer{enum{value=true};};
模板
typename boost::enable_if::type
操作符这已经编辑了几次,我们决定调用包装集合的主类RangePrinter
一旦您编写了一次性操作符此解决方案受Marcelo解决方案的启发,并进行了一些更改,它将自动适用于任何集合:
#include <iostream>
#include <iterator>
#include <type_traits>
#include <vector>
#include <algorithm>
// This works similar to ostream_iterator, but doesn't print a delimiter after the final item
template<typename T, typename TChar = char, typename TCharTraits = std::char_traits<TChar> >
class pretty_ostream_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef TChar char_type;
typedef TCharTraits traits_type;
typedef std::basic_ostream<TChar, TCharTraits> ostream_type;
pretty_ostream_iterator(ostream_type &stream, const char_type *delim = NULL)
: _stream(&stream), _delim(delim), _insertDelim(false)
{
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator=(const T &value)
{
if( _delim != NULL )
{
// Don't insert a delimiter if this is the first time the function is called
if( _insertDelim )
(*_stream) << _delim;
else
_insertDelim = true;
}
(*_stream) << value;
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator*()
{
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator++()
{
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator++(int)
{
return *this;
}
private:
ostream_type *_stream;
const char_type *_delim;
bool _insertDelim;
};
#if _MSC_VER >= 1400
// Declare pretty_ostream_iterator as checked
template<typename T, typename TChar, typename TCharTraits>
struct std::_Is_checked_helper<pretty_ostream_iterator<T, TChar, TCharTraits> > : public std::tr1::true_type
{
};
#endif // _MSC_VER >= 1400
namespace std
{
// Pre-declarations of container types so we don't actually have to include the relevant headers if not needed, speeding up compilation time.
// These aren't necessary if you do actually include the headers.
template<typename T, typename TAllocator> class vector;
template<typename T, typename TAllocator> class list;
template<typename T, typename TTraits, typename TAllocator> class set;
template<typename TKey, typename TValue, typename TTraits, typename TAllocator> class map;
}
// Basic is_container template; specialize to derive from std::true_type for all desired container types
template<typename T> struct is_container : public std::false_type { };
// Mark vector as a container
template<typename T, typename TAllocator> struct is_container<std::vector<T, TAllocator> > : public std::true_type { };
// Mark list as a container
template<typename T, typename TAllocator> struct is_container<std::list<T, TAllocator> > : public std::true_type { };
// Mark set as a container
template<typename T, typename TTraits, typename TAllocator> struct is_container<std::set<T, TTraits, TAllocator> > : public std::true_type { };
// Mark map as a container
template<typename TKey, typename TValue, typename TTraits, typename TAllocator> struct is_container<std::map<TKey, TValue, TTraits, TAllocator> > : public std::true_type { };
// Holds the delimiter values for a specific character type
template<typename TChar>
struct delimiters_values
{
typedef TChar char_type;
const TChar *prefix;
const TChar *delimiter;
const TChar *postfix;
};
// Defines the delimiter values for a specific container and character type
template<typename T, typename TChar>
struct delimiters
{
static const delimiters_values<TChar> values;
};
// Default delimiters
template<typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
template<typename T> const delimiters_values<char> delimiters<T, char>::values = { "{ ", ", ", " }" };
template<typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
template<typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"{ ", L", ", L" }" };
// Delimiters for set
template<typename T, typename TTraits, typename TAllocator> struct delimiters<std::set<T, TTraits, TAllocator>, char> { static const delimiters_values<char> values; };
template<typename T, typename TTraits, typename TAllocator> const delimiters_values<char> delimiters<std::set<T, TTraits, TAllocator>, char>::values = { "[ ", ", ", " ]" };
template<typename T, typename TTraits, typename TAllocator> struct delimiters<std::set<T, TTraits, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
template<typename T, typename TTraits, typename TAllocator> const delimiters_values<wchar_t> delimiters<std::set<T, TTraits, TAllocator>, wchar_t>::values = { L"[ ", L", ", L" ]" };
// Delimiters for pair
template<typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
template<typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
template<typename T1, typename T2> struct delimiters<std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
template<typename T1, typename T2> const delimiters_values<wchar_t> delimiters<std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
// Functor to print containers. You can use this directly if you want to specificy a non-default delimiters type.
template<typename T, typename TChar = char, typename TCharTraits = std::char_traits<TChar>, typename TDelimiters = delimiters<T, TChar> >
struct print_container_helper
{
typedef TChar char_type;
typedef TDelimiters delimiters_type;
typedef std::basic_ostream<TChar, TCharTraits>& ostream_type;
print_container_helper(const T &container)
: _container(&container)
{
}
void operator()(ostream_type &stream) const
{
if( delimiters_type::values.prefix != NULL )
stream << delimiters_type::values.prefix;
std::copy(_container->begin(), _container->end(), pretty_ostream_iterator<typename T::value_type, TChar, TCharTraits>(stream, delimiters_type::values.delimiter));
if( delimiters_type::values.postfix != NULL )
stream << delimiters_type::values.postfix;
}
private:
const T *_container;
};
// Prints a print_container_helper to the specified stream.
template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
std::basic_ostream<TChar, TCharTraits>& operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const print_container_helper<T, TChar, TDelimiters> &helper)
{
helper(stream);
return stream;
}
// Prints a container to the stream using default delimiters
template<typename T, typename TChar, typename TCharTraits>
typename std::enable_if<is_container<T>::value, std::basic_ostream<TChar, TCharTraits>&>::type
operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const T &container)
{
stream << print_container_helper<T, TChar, TCharTraits>(container);
return stream;
}
// Prints a pair to the stream using delimiters from delimiters<std::pair<T1, T2>>.
template<typename T1, typename T2, typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits>& operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const std::pair<T1, T2> &value)
{
if( delimiters<std::pair<T1, T2>, TChar>::values.prefix != NULL )
stream << delimiters<std::pair<T1, T2>, TChar>::values.prefix;
stream << value.first;
if( delimiters<std::pair<T1, T2>, TChar>::values.delimiter != NULL )
stream << delimiters<std::pair<T1, T2>, TChar>::values.delimiter;
stream << value.second;
if( delimiters<std::pair<T1, T2>, TChar>::values.postfix != NULL )
stream << delimiters<std::pair<T1, T2>, TChar>::values.postfix;
return stream;
}
// Used by the sample below to generate some values
struct fibonacci
{
fibonacci() : f1(0), f2(1) { }
int operator()()
{
int r = f1 + f2;
f1 = f2;
f2 = r;
return f1;
}
private:
int f1;
int f2;
};
int main()
{
std::vector<int> v;
std::generate_n(std::back_inserter(v), 10, fibonacci());
std::cout << v << std::endl;
// Example of using pretty_ostream_iterator directly
std::generate_n(pretty_ostream_iterator<int>(std::cout, ";"), 20, fibonacci());
std::cout << std::endl;
}
#包括
#包括
#包括
#包括
#包括
//这与ostream_迭代器类似,但不会在最后一项后打印分隔符
模板
类pretty_ostream_迭代器:public std::iterator
{
公众:
typedef TChar char_类型;
typedef-TCharTraits-traits_-type;
typedef std::基本类型类型;
pretty_ostream_迭代器(ostream_类型和流,const char_类型*delim=NULL)
:_stream(&stream),_delim(delim),_insertDelim(false)
{
}
pretty_ostream_迭代器和运算符=(常量T和值)
{
如果(_delim!=NULL)
{
//如果这是第一次调用函数,请不要插入分隔符
如果(_insertDelim)
(*_-stream)=1400
名称空间标准
{
//预先声明容器类型,因此如果不需要,实际上不必包含相关的头,从而加快编译时间。
//如果确实包含了标题,则不需要这些。
模板类向量;
模板类列表;
模板类集合;
模板类映射;
}
//Basic是_容器模板;专门化为从std::true_类型派生所有所需的容器类型
模板结构是_容器:public std::false_type{};
//将向量标记为容器
模板结构是_容器:public std::true_type{};
//将列表标记为容器
模板结构是_容器:public std::true_type{};
//作为容器设置的标记
模板结构是_容器:public std::true_type{};
//将地图标记为容器
模板结构是_容器:public std::true_type{};
//保存特定字符类型的分隔符值
模板
结构分隔符\u值
{
typedef TChar char_类型;
常量TChar*前缀;
常量TChar*分隔符;
常量TChar*后缀;
};
//定义特定容器和字符类型的分隔符值
模板
结构分隔符
{
静态常量分隔符\u值;
};
//默认分隔符
模板结构分隔符{static const delimiters_values;};
模板常量分隔符\值分隔符::值={{{,“,”,“}”;
模板结构分隔符{static const delimiters_values;};
模板常量分隔符\u值分隔符::值={L“{”,L“,”,L“}”;
//集合的分隔符
模板结构分隔符{static const delimiters_values;};
模板常量分隔符\u值分隔符::值={“[”,“,”,“]”};
模板结构分隔符{static const delimiters_values;};
模板常量分隔符\u值分隔符::值={L“[”,L“,”,L“]”};
//对的分隔符
模板结构分隔符{static const delimiters_values;};
模板常量分隔符\ U值分隔符::值={“(”,“,”,“,”,”)};
模板结构分隔符{static const delimiters_values;};
模板常量分隔符\ U值分隔符::值={L”(“,L“,”,L“)”};
//用于打印容器的函子。如果要指定非默认分隔符类型,可以直接使用此函数。
模板
结构打印容器辅助程序
{
typedef TChar char_类型;
typedef TDelimiters分隔符_type;
typedef std::基本的ostream和ostream类型;
打印容器辅助程序(常量和容器)
:_容器(&容器)
{
}
void运算符()(ostream_类型和流)常量
{
if(分隔符类型::values.prefix!=NULL)
stream begin(),_container->end(),pretty_ostream_迭代器(stream,delimiters\u type::values.delimiter));
if(分隔符类型::values.postfix!=NULL)
stream我的解决方案是,这是软件包的一部分。所有std容器、地图、集合、c阵列都可以打印。问题可能在前面的循环中:
(x = 17; isalpha(firstsquare); x++)
这个循环根本不会运行(如果firstsquare
是非字母的)或者将永远运行(如果它是字母的)。原因是firstsquare
不会随着x
的增加而改变。我看到了两个问题。如中所指出的
for (x = 17; isalpha(firstsquare); x++)
有一个无限循环或者根本不执行,在if(entrance='s')
中,如果入口字符不同于's'
,则不会将任何内容推送到路径向量,使其为空,从而不会在屏幕上打印任何内容。您可以测试后者是否检查path.empty()
或打印path.size()
无论哪种方式,使用字符串而不是向量不是更好吗?您也可以像数组一样访问字符串内容、查找字符、提取子字符串并轻松打印字符串(无需循环)
用字符串来完成这一切可能是以一种不太复杂的方式编写它并使之成为ea的一种方式
template<typename Collection>
RangePrinter<typename Collection::const_iterator> rangePrinter
( const Collection& coll, const char * delim=",",
const char * open="[", const char * close="]")
{
return RangePrinter< typename Collection::const_iterator >
( coll.begin(), coll.end(), delim, open, close );
}
std::cout << outputFormatter( mySet );
#include <iostream>
#include <iterator>
#include <type_traits>
#include <vector>
#include <algorithm>
// This works similar to ostream_iterator, but doesn't print a delimiter after the final item
template<typename T, typename TChar = char, typename TCharTraits = std::char_traits<TChar> >
class pretty_ostream_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef TChar char_type;
typedef TCharTraits traits_type;
typedef std::basic_ostream<TChar, TCharTraits> ostream_type;
pretty_ostream_iterator(ostream_type &stream, const char_type *delim = NULL)
: _stream(&stream), _delim(delim), _insertDelim(false)
{
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator=(const T &value)
{
if( _delim != NULL )
{
// Don't insert a delimiter if this is the first time the function is called
if( _insertDelim )
(*_stream) << _delim;
else
_insertDelim = true;
}
(*_stream) << value;
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator*()
{
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator++()
{
return *this;
}
pretty_ostream_iterator<T, TChar, TCharTraits>& operator++(int)
{
return *this;
}
private:
ostream_type *_stream;
const char_type *_delim;
bool _insertDelim;
};
#if _MSC_VER >= 1400
// Declare pretty_ostream_iterator as checked
template<typename T, typename TChar, typename TCharTraits>
struct std::_Is_checked_helper<pretty_ostream_iterator<T, TChar, TCharTraits> > : public std::tr1::true_type
{
};
#endif // _MSC_VER >= 1400
namespace std
{
// Pre-declarations of container types so we don't actually have to include the relevant headers if not needed, speeding up compilation time.
// These aren't necessary if you do actually include the headers.
template<typename T, typename TAllocator> class vector;
template<typename T, typename TAllocator> class list;
template<typename T, typename TTraits, typename TAllocator> class set;
template<typename TKey, typename TValue, typename TTraits, typename TAllocator> class map;
}
// Basic is_container template; specialize to derive from std::true_type for all desired container types
template<typename T> struct is_container : public std::false_type { };
// Mark vector as a container
template<typename T, typename TAllocator> struct is_container<std::vector<T, TAllocator> > : public std::true_type { };
// Mark list as a container
template<typename T, typename TAllocator> struct is_container<std::list<T, TAllocator> > : public std::true_type { };
// Mark set as a container
template<typename T, typename TTraits, typename TAllocator> struct is_container<std::set<T, TTraits, TAllocator> > : public std::true_type { };
// Mark map as a container
template<typename TKey, typename TValue, typename TTraits, typename TAllocator> struct is_container<std::map<TKey, TValue, TTraits, TAllocator> > : public std::true_type { };
// Holds the delimiter values for a specific character type
template<typename TChar>
struct delimiters_values
{
typedef TChar char_type;
const TChar *prefix;
const TChar *delimiter;
const TChar *postfix;
};
// Defines the delimiter values for a specific container and character type
template<typename T, typename TChar>
struct delimiters
{
static const delimiters_values<TChar> values;
};
// Default delimiters
template<typename T> struct delimiters<T, char> { static const delimiters_values<char> values; };
template<typename T> const delimiters_values<char> delimiters<T, char>::values = { "{ ", ", ", " }" };
template<typename T> struct delimiters<T, wchar_t> { static const delimiters_values<wchar_t> values; };
template<typename T> const delimiters_values<wchar_t> delimiters<T, wchar_t>::values = { L"{ ", L", ", L" }" };
// Delimiters for set
template<typename T, typename TTraits, typename TAllocator> struct delimiters<std::set<T, TTraits, TAllocator>, char> { static const delimiters_values<char> values; };
template<typename T, typename TTraits, typename TAllocator> const delimiters_values<char> delimiters<std::set<T, TTraits, TAllocator>, char>::values = { "[ ", ", ", " ]" };
template<typename T, typename TTraits, typename TAllocator> struct delimiters<std::set<T, TTraits, TAllocator>, wchar_t> { static const delimiters_values<wchar_t> values; };
template<typename T, typename TTraits, typename TAllocator> const delimiters_values<wchar_t> delimiters<std::set<T, TTraits, TAllocator>, wchar_t>::values = { L"[ ", L", ", L" ]" };
// Delimiters for pair
template<typename T1, typename T2> struct delimiters<std::pair<T1, T2>, char> { static const delimiters_values<char> values; };
template<typename T1, typename T2> const delimiters_values<char> delimiters<std::pair<T1, T2>, char>::values = { "(", ", ", ")" };
template<typename T1, typename T2> struct delimiters<std::pair<T1, T2>, wchar_t> { static const delimiters_values<wchar_t> values; };
template<typename T1, typename T2> const delimiters_values<wchar_t> delimiters<std::pair<T1, T2>, wchar_t>::values = { L"(", L", ", L")" };
// Functor to print containers. You can use this directly if you want to specificy a non-default delimiters type.
template<typename T, typename TChar = char, typename TCharTraits = std::char_traits<TChar>, typename TDelimiters = delimiters<T, TChar> >
struct print_container_helper
{
typedef TChar char_type;
typedef TDelimiters delimiters_type;
typedef std::basic_ostream<TChar, TCharTraits>& ostream_type;
print_container_helper(const T &container)
: _container(&container)
{
}
void operator()(ostream_type &stream) const
{
if( delimiters_type::values.prefix != NULL )
stream << delimiters_type::values.prefix;
std::copy(_container->begin(), _container->end(), pretty_ostream_iterator<typename T::value_type, TChar, TCharTraits>(stream, delimiters_type::values.delimiter));
if( delimiters_type::values.postfix != NULL )
stream << delimiters_type::values.postfix;
}
private:
const T *_container;
};
// Prints a print_container_helper to the specified stream.
template<typename T, typename TChar, typename TCharTraits, typename TDelimiters>
std::basic_ostream<TChar, TCharTraits>& operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const print_container_helper<T, TChar, TDelimiters> &helper)
{
helper(stream);
return stream;
}
// Prints a container to the stream using default delimiters
template<typename T, typename TChar, typename TCharTraits>
typename std::enable_if<is_container<T>::value, std::basic_ostream<TChar, TCharTraits>&>::type
operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const T &container)
{
stream << print_container_helper<T, TChar, TCharTraits>(container);
return stream;
}
// Prints a pair to the stream using delimiters from delimiters<std::pair<T1, T2>>.
template<typename T1, typename T2, typename TChar, typename TCharTraits>
std::basic_ostream<TChar, TCharTraits>& operator<<(std::basic_ostream<TChar, TCharTraits> &stream, const std::pair<T1, T2> &value)
{
if( delimiters<std::pair<T1, T2>, TChar>::values.prefix != NULL )
stream << delimiters<std::pair<T1, T2>, TChar>::values.prefix;
stream << value.first;
if( delimiters<std::pair<T1, T2>, TChar>::values.delimiter != NULL )
stream << delimiters<std::pair<T1, T2>, TChar>::values.delimiter;
stream << value.second;
if( delimiters<std::pair<T1, T2>, TChar>::values.postfix != NULL )
stream << delimiters<std::pair<T1, T2>, TChar>::values.postfix;
return stream;
}
// Used by the sample below to generate some values
struct fibonacci
{
fibonacci() : f1(0), f2(1) { }
int operator()()
{
int r = f1 + f2;
f1 = f2;
f2 = r;
return f1;
}
private:
int f1;
int f2;
};
int main()
{
std::vector<int> v;
std::generate_n(std::back_inserter(v), 10, fibonacci());
std::cout << v << std::endl;
// Example of using pretty_ostream_iterator directly
std::generate_n(pretty_ostream_iterator<int>(std::cout, ";"), 20, fibonacci());
std::cout << std::endl;
}
(x = 17; isalpha(firstsquare); x++)
for (x = 17; isalpha(firstsquare); x++)
std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
typedef std::vector<char> Path; // 'Path' now a synonym for the vector
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
using Path = std::vector<char>; // C++11 onwards only
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
// Path typedef'd to std::vector<char>
for( Path::size_type i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
for (auto i: path)
std::cout << i << ' ';
for (const auto i: path)
std::cout << i << ' ';
for (auto& i: path)
std::cout << i << ' ';
for (const auto& i: path)
std::cout << i << ' ';
#include <iterator> // needed for std::ostram_iterator
template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
if ( !v.empty() ) {
out << '[';
std::copy (v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
out << "\b\b]";
}
return out;
}
#include <iostream>
#include <algorithm> // for copy
#include <iterator> // for ostream_iterator
#include <vector>
int main() {
/* Set up vector to hold chars a-z */
std::vector<char> path;
for (int ch = 'a'; ch <= 'z'; ++ch)
path.push_back(ch);
/* Print path vector to console */
std::copy(path.begin(), path.end(), std::ostream_iterator<char>(std::cout, " "));
return 0;
}
for (auto const& c : path)
std::cout << c << ' ';
#include <vector>
using std::vector;
#include <iostream>
using std::ostream;
template<typename T>
ostream& operator<< (ostream& out, const vector<T>& v) {
out << "{";
size_t last = v.size() - 1;
for(size_t i = 0; i < v.size(); ++i) {
out << v[i];
if (i != last)
out << ", ";
}
out << "}";
return out;
}
vector<string> s = {"first", "second", "third"};
vector<bool> b = {true, false, true, false, false};
vector<int> i = {1, 2, 3, 4};
cout << s << endl;
cout << b << endl;
cout << i << endl;
{first, second, third}
{1, 0, 1, 0, 0}
{1, 2, 3, 4}
#include <vector>
#include <algorithm>
// ...
std::vector<char> vec;
// ...
std::for_each(
vec.cbegin(),
vec.cend(),
[] (const char c) {std::cout << c << " ";}
);
// ...
namespace details {
using std::begin; using std::end;
template<class T, class=void>
struct is_iterable_test:std::false_type{};
template<class T>
struct is_iterable_test<T,
decltype((void)(
(void)(begin(std::declval<T>())==end(std::declval<T>()))
, ((void)(std::next(begin(std::declval<T>()))))
, ((void)(*begin(std::declval<T>())))
, 1
))
>:std::true_type{};
template<class T>struct is_tupleoid:std::false_type{};
template<class...Ts>struct is_tupleoid<std::tuple<Ts...>>:std::true_type{};
template<class...Ts>struct is_tupleoid<std::pair<Ts...>>:std::true_type{};
// template<class T, size_t N>struct is_tupleoid<std::array<T,N>>:std::true_type{}; // complete, but problematic
}
template<class T>struct is_iterable:details::is_iterable_test<std::decay_t<T>>{};
template<class T, std::size_t N>struct is_iterable<T(&)[N]>:std::true_type{}; // bypass decay
template<class T>struct is_tupleoid:details::is_tupleoid<std::decay_t<T>>{};
template<class T>struct is_visitable:std::integral_constant<bool, is_iterable<T>{}||is_tupleoid<T>{}> {};
template<class C, class F>
std::enable_if_t<is_iterable<C>{}> visit_first(C&& c, F&& f) {
using std::begin; using std::end;
auto&& b = begin(c);
auto&& e = end(c);
if (b==e)
return;
std::forward<F>(f)(*b);
}
template<class C, class F>
std::enable_if_t<is_iterable<C>{}> visit_all_but_first(C&& c, F&& f) {
using std::begin; using std::end;
auto it = begin(c);
auto&& e = end(c);
if (it==e)
return;
it = std::next(it);
for( ; it!=e; it = std::next(it) ) {
f(*it);
}
}
namespace details {
template<class Tup, class F>
void visit_first( std::index_sequence<>, Tup&&, F&& ) {}
template<size_t... Is, class Tup, class F>
void visit_first( std::index_sequence<0,Is...>, Tup&& tup, F&& f ) {
std::forward<F>(f)( std::get<0>( std::forward<Tup>(tup) ) );
}
template<class Tup, class F>
void visit_all_but_first( std::index_sequence<>, Tup&&, F&& ) {}
template<size_t... Is,class Tup, class F>
void visit_all_but_first( std::index_sequence<0,Is...>, Tup&& tup, F&& f ) {
int unused[] = {0,((void)(
f( std::get<Is>(std::forward<Tup>(tup)) )
),0)...};
(void)(unused);
}
}
template<class Tup, class F>
std::enable_if_t<is_tupleoid<Tup>{}> visit_first(Tup&& tup, F&& f) {
details::visit_first( std::make_index_sequence< std::tuple_size<std::decay_t<Tup>>{} >{}, std::forward<Tup>(tup), std::forward<F>(f) );
}
template<class Tup, class F>
std::enable_if_t<is_tupleoid<Tup>{}> visit_all_but_first(Tup&& tup, F&& f) {
details::visit_all_but_first( std::make_index_sequence< std::tuple_size<std::decay_t<Tup>>{} >{}, std::forward<Tup>(tup), std::forward<F>(f) );
}
namespace pretty_print {
namespace decorator {
struct default_tag {};
template<class Old>
struct map_magic_tag:Old {}; // magic for maps
// Maps get {}s. Write trait `is_associative` to generalize:
template<class CharT, class Traits, class...Xs >
void pretty_print_before( default_tag, std::basic_ostream<CharT, Traits>& s, std::map<Xs...> const& ) {
s << CharT('{');
}
template<class CharT, class Traits, class...Xs >
void pretty_print_after( default_tag, std::basic_ostream<CharT, Traits>& s, std::map<Xs...> const& ) {
s << CharT('}');
}
// tuples and pairs get ():
template<class CharT, class Traits, class Tup >
std::enable_if_t<is_tupleoid<Tup>{}> pretty_print_before( default_tag, std::basic_ostream<CharT, Traits>& s, Tup const& ) {
s << CharT('(');
}
template<class CharT, class Traits, class Tup >
std::enable_if_t<is_tupleoid<Tup>{}> pretty_print_after( default_tag, std::basic_ostream<CharT, Traits>& s, Tup const& ) {
s << CharT(')');
}
// strings with the same character type get ""s:
template<class CharT, class Traits, class...Xs >
void pretty_print_before( default_tag, std::basic_ostream<CharT, Traits>& s, std::basic_string<CharT, Xs...> const& ) {
s << CharT('"');
}
template<class CharT, class Traits, class...Xs >
void pretty_print_after( default_tag, std::basic_ostream<CharT, Traits>& s, std::basic_string<CharT, Xs...> const& ) {
s << CharT('"');
}
// and pack the characters together:
template<class CharT, class Traits, class...Xs >
void pretty_print_between( default_tag, std::basic_ostream<CharT, Traits>&, std::basic_string<CharT, Xs...> const& ) {}
// map magic. When iterating over the contents of a map, use the map_magic_tag:
template<class...Xs>
map_magic_tag<default_tag> pretty_print_descend( default_tag, std::map<Xs...> const& ) {
return {};
}
template<class old_tag, class C>
old_tag pretty_print_descend( map_magic_tag<old_tag>, C const& ) {
return {};
}
// When printing a pair immediately within a map, use -> as a separator:
template<class old_tag, class CharT, class Traits, class...Xs >
void pretty_print_between( map_magic_tag<old_tag>, std::basic_ostream<CharT, Traits>& s, std::pair<Xs...> const& ) {
s << CharT('-') << CharT('>');
}
}
// default behavior:
template<class CharT, class Traits, class Tag, class Container >
void pretty_print_before( Tag const&, std::basic_ostream<CharT, Traits>& s, Container const& ) {
s << CharT('[');
}
template<class CharT, class Traits, class Tag, class Container >
void pretty_print_after( Tag const&, std::basic_ostream<CharT, Traits>& s, Container const& ) {
s << CharT(']');
}
template<class CharT, class Traits, class Tag, class Container >
void pretty_print_between( Tag const&, std::basic_ostream<CharT, Traits>& s, Container const& ) {
s << CharT(',');
}
template<class Tag, class Container>
Tag&& pretty_print_descend( Tag&& tag, Container const& ) {
return std::forward<Tag>(tag);
}
// print things by default by using <<:
template<class Tag=decorator::default_tag, class Scalar, class CharT, class Traits>
std::enable_if_t<!is_visitable<Scalar>{}> print( std::basic_ostream<CharT, Traits>& os, Scalar&& scalar, Tag&&=Tag{} ) {
os << std::forward<Scalar>(scalar);
}
// for anything visitable (see above), use the pretty print algorithm:
template<class Tag=decorator::default_tag, class C, class CharT, class Traits>
std::enable_if_t<is_visitable<C>{}> print( std::basic_ostream<CharT, Traits>& os, C&& c, Tag&& tag=Tag{} ) {
pretty_print_before( std::forward<Tag>(tag), os, std::forward<C>(c) );
visit_first( c, [&](auto&& elem) {
print( os, std::forward<decltype(elem)>(elem), pretty_print_descend( std::forward<Tag>(tag), std::forward<C>(c) ) );
});
visit_all_but_first( c, [&](auto&& elem) {
pretty_print_between( std::forward<Tag>(tag), os, std::forward<C>(c) );
print( os, std::forward<decltype(elem)>(elem), pretty_print_descend( std::forward<Tag>(tag), std::forward<C>(c) ) );
});
pretty_print_after( std::forward<Tag>(tag), os, std::forward<C>(c) );
}
}
int main() {
std::vector<int> x = {1,2,3};
pretty_print::print( std::cout, x );
std::cout << "\n";
std::map< std::string, int > m;
m["hello"] = 3;
m["world"] = 42;
pretty_print::print( std::cout, m );
std::cout << "\n";
}
vector<char> items = {'a','b','c'};
for (char n : items)
cout << n << ' ';
a b c
std::vector<int> v{1,2,3,4};
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout, " " ));
1 2 3 4
#include <vector>
#include "pretty.h"
int main()
{
std::cout << std::vector<int>{1,2,3,4,5}; // prints 1, 2, 3, 4, 5
return 0;
}
#include <vector>
#include "pretty.h"
int main()
{
// set decoration for std::vector<int> for cout object
std::cout << pretty::decoration<std::vector<int>>("(", ",", ")");
std::cout << std::vector<int>{1,2,3,4,5}; // prints (1,2,3,4,5)
return 0;
}
#include <vector>
#include "pretty.h"
// set decoration for std::vector<int> for all ostream objects
PRETTY_DEFAULT_DECORATION(std::vector<int>, "{", ", ", "}")
int main()
{
std::cout << std::vector<int>{1,2,3,4,5}; // prints {1, 2, 3, 4, 5}
std::cout << pretty::decoration<std::vector<int>>("(", ",", ")");
std::cout << std::vector<int>{1,2,3,4,5}; // prints (1,2,3,4,5)
return 0;
}
namespace pretty
{
template<class T, std::size_t N>
struct defaulted<T[N]>
{
static decor<T[N]> decoration()
{
return{ { "(" }, { ":" }, { ")" } };
}
};
}
float e[5] = { 3.4f, 4.3f, 5.2f, 1.1f, 22.2f };
std::cout << e << '\n'; // prints (3.4:4.3:5.2:1.1:22.2)
namespace pretty {
template< __VA_ARGS__ >
struct defaulted< TYPE > {
static decor< TYPE > decoration() {
return { PREFIX, DELIM, POSTFIX };
}
};
}
PRETTY_DEFAULT_DECORATION(T[N], "", ";", "", class T, std::size_t N)
PRETTY_DEFAULT_DECORATION(std::vector<int>, "(", ", ", ")")
float e[3] = { 3.4f, 4.3f, 5.2f };
std::stringstream u;
// add { ; } decoration to u
u << pretty::decoration<float[3]>("{", "; ", "}");
// use { ; } decoration
u << e << '\n'; // prints {3.4; 4.3; 5.2}
// uses decoration returned by defaulted<float[3]>::decoration()
std::cout << e; // prints 3.4, 4.3, 5.2
PRETTY_DEFAULT_DECORATION(float[3], "{{{", ",", "}}}")
std::stringstream v;
v << e; // prints {{{3.4,4.3,5.2}}}
v << pretty::decoration<float[3]>(":");
v << e; // prints {{{3.4:4.3:5.2}}}
v << pretty::decoration<float[3]>("((", "=", "))");
v << e; // prints ((3.4=4.3=5.2))
s << pretty::clear<std::vector<int>>();
std::vector<std::vector<int>> m{ {1,2,3}, {4,5,6}, {7,8,9} };
std::cout << pretty::decoration<std::vector<std::vector<int>>>("\n");
std::cout << m;
1, 2, 3
4, 5, 6
7, 8, 9
#ifndef pretty_print_0x57547_sa4884X_0_1_h_guard_
#define pretty_print_0x57547_sa4884X_0_1_h_guard_
#include <string>
#include <iostream>
#include <type_traits>
#include <iterator>
#include <utility>
#define PRETTY_DEFAULT_DECORATION(TYPE, PREFIX, DELIM, POSTFIX, ...) \
namespace pretty { template< __VA_ARGS__ >\
struct defaulted< TYPE > {\
static decor< TYPE > decoration(){\
return { PREFIX, DELIM, POSTFIX };\
} /*decoration*/ }; /*defaulted*/} /*pretty*/
#define PRETTY_DEFAULT_WDECORATION(TYPE, PREFIX, DELIM, POSTFIX, ...) \
namespace pretty { template< __VA_ARGS__ >\
struct defaulted< TYPE, wchar_t, std::char_traits<wchar_t> > {\
static decor< TYPE, wchar_t, std::char_traits<wchar_t> > decoration(){\
return { PREFIX, DELIM, POSTFIX };\
} /*decoration*/ }; /*defaulted*/} /*pretty*/
namespace pretty
{
namespace detail
{
// drag in begin and end overloads
using std::begin;
using std::end;
// helper template
template <int I> using _ol = std::integral_constant<int, I>*;
// SFINAE check whether T is a range with begin/end
template<class T>
class is_range
{
// helper function declarations using expression sfinae
template <class U, _ol<0> = nullptr>
static std::false_type b(...);
template <class U, _ol<1> = nullptr>
static auto b(U &v) -> decltype(begin(v), std::true_type());
template <class U, _ol<0> = nullptr>
static std::false_type e(...);
template <class U, _ol<1> = nullptr>
static auto e(U &v) -> decltype(end(v), std::true_type());
// return types
using b_return = decltype(b<T>(std::declval<T&>()));
using e_return = decltype(e<T>(std::declval<T&>()));
public:
static const bool value = b_return::value && e_return::value;
};
}
// holder class for data
template<class T, class CharT = char, class TraitT = std::char_traits<CharT>>
struct decor
{
static const int xindex;
std::basic_string<CharT, TraitT> prefix, delimiter, postfix;
decor(std::basic_string<CharT, TraitT> const & pre = "",
std::basic_string<CharT, TraitT> const & delim = "",
std::basic_string<CharT, TraitT> const & post = "")
: prefix(pre), delimiter(delim), postfix(post) {}
};
template<class T, class charT, class traits>
int const decor<T, charT, traits>::xindex = std::ios_base::xalloc();
namespace detail
{
template<class T, class CharT, class TraitT>
void manage_decor(std::ios_base::event evt, std::ios_base &s, int const idx)
{
using deco_type = decor<T, CharT, TraitT>;
if (evt == std::ios_base::erase_event)
{ // erase deco
void const * const p = s.pword(idx);
if (p)
{
delete static_cast<deco_type const * const>(p);
s.pword(idx) = nullptr;
}
}
else if (evt == std::ios_base::copyfmt_event)
{ // copy deco
void const * const p = s.pword(idx);
if (p)
{
auto np = new deco_type{ *static_cast<deco_type const * const>(p) };
s.pword(idx) = static_cast<void*>(np);
}
}
}
template<class T> struct clearer {};
template<class T, class CharT, class TraitT>
std::basic_ostream<CharT, TraitT>& operator<< (
std::basic_ostream<CharT, TraitT> &s, clearer<T> const &)
{
using deco_type = decor<T, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
if (p)
{ // delete if set
delete static_cast<deco_type const *>(p);
s.pword(deco_type::xindex) = nullptr;
}
return s;
}
template <class CharT>
struct default_data { static const CharT * decor[3]; };
template <>
const char * default_data<char>::decor[3] = { "", ", ", "" };
template <>
const wchar_t * default_data<wchar_t>::decor[3] = { L"", L", ", L"" };
}
// Clear decoration for T
template<class T>
detail::clearer<T> clear() { return{}; }
template<class T, class CharT, class TraitT>
void clear(std::basic_ostream<CharT, TraitT> &s) { s << detail::clearer<T>{}; }
// impose decoration on ostream
template<class T, class CharT, class TraitT>
std::basic_ostream<CharT, TraitT>& operator<<(
std::basic_ostream<CharT, TraitT> &s, decor<T, CharT, TraitT> && h)
{
using deco_type = decor<T, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
// delete if already set
if (p) delete static_cast<deco_type const *>(p);
s.pword(deco_type::xindex) = static_cast<void *>(new deco_type{ std::move(h) });
// check whether we alread have a callback registered
if (s.iword(deco_type::xindex) == 0)
{ // if this is not the case register callback and set iword
s.register_callback(detail::manage_decor<T, CharT, TraitT>, deco_type::xindex);
s.iword(deco_type::xindex) = 1;
}
return s;
}
template<class T, class CharT = char, class TraitT = std::char_traits<CharT>>
struct defaulted
{
static inline decor<T, CharT, TraitT> decoration()
{
return{ detail::default_data<CharT>::decor[0],
detail::default_data<CharT>::decor[1],
detail::default_data<CharT>::decor[2] };
}
};
template<class T, class CharT = char, class TraitT = std::char_traits<CharT>>
decor<T, CharT, TraitT> decoration(
std::basic_string<CharT, TraitT> const & prefix,
std::basic_string<CharT, TraitT> const & delimiter,
std::basic_string<CharT, TraitT> const & postfix)
{
return{ prefix, delimiter, postfix };
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
decor<T, CharT, TraitT> decoration(
std::basic_string<CharT, TraitT> const & delimiter)
{
using str_type = std::basic_string<CharT, TraitT>;
return{ defaulted<T, CharT, TraitT>::decoration().prefix,
delimiter, defaulted<T, CharT, TraitT>::decoration().postfix };
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
decor<T, CharT, TraitT> decoration(CharT const * const prefix,
CharT const * const delimiter, CharT const * const postfix)
{
using str_type = std::basic_string<CharT, TraitT>;
return{ str_type{ prefix }, str_type{ delimiter }, str_type{ postfix } };
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
decor<T, CharT, TraitT> decoration(CharT const * const delimiter)
{
using str_type = std::basic_string<CharT, TraitT>;
return{ defaulted<T, CharT, TraitT>::decoration().prefix,
str_type{ delimiter }, defaulted<T, CharT, TraitT>::decoration().postfix };
}
template<typename T, std::size_t N, std::size_t L>
struct tuple
{
template<class CharT, class TraitT>
static void print(std::basic_ostream<CharT, TraitT>& s, T const & value,
std::basic_string<CharT, TraitT> const &delimiter)
{
s << std::get<N>(value) << delimiter;
tuple<T, N + 1, L>::print(s, value, delimiter);
}
};
template<typename T, std::size_t N>
struct tuple<T, N, N>
{
template<class CharT, class TraitT>
static void print(std::basic_ostream<CharT, TraitT>& s, T const & value,
std::basic_string<CharT, TraitT> const &) {
s << std::get<N>(value);
}
};
}
template<class CharT, class TraitT>
std::basic_ostream<CharT, TraitT> & operator<< (
std::basic_ostream<CharT, TraitT> &s, std::tuple<> const & v)
{
using deco_type = pretty::decor<std::tuple<void*>, CharT, TraitT>;
using defaulted_type = pretty::defaulted<std::tuple<void*>, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
auto const d = static_cast<deco_type const * const>(p);
s << (d ? d->prefix : defaulted_type::decoration().prefix);
s << (d ? d->postfix : defaulted_type::decoration().postfix);
return s;
}
template<class CharT, class TraitT, class ... T>
std::basic_ostream<CharT, TraitT> & operator<< (
std::basic_ostream<CharT, TraitT> &s, std::tuple<T...> const & v)
{
using deco_type = pretty::decor<std::tuple<void*>, CharT, TraitT>;
using defaulted_type = pretty::defaulted<std::tuple<void*>, CharT, TraitT>;
using pretty_tuple = pretty::tuple<std::tuple<T...>, 0U, sizeof...(T)-1U>;
void const * const p = s.pword(deco_type::xindex);
auto const d = static_cast<deco_type const * const>(p);
s << (d ? d->prefix : defaulted_type::decoration().prefix);
pretty_tuple::print(s, v, d ? d->delimiter :
defaulted_type::decoration().delimiter);
s << (d ? d->postfix : defaulted_type::decoration().postfix);
return s;
}
template<class T, class U, class CharT, class TraitT>
std::basic_ostream<CharT, TraitT> & operator<< (
std::basic_ostream<CharT, TraitT> &s, std::pair<T, U> const & v)
{
using deco_type = pretty::decor<std::pair<T, U>, CharT, TraitT>;
using defaulted_type = pretty::defaulted<std::pair<T, U>, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
auto const d = static_cast<deco_type const * const>(p);
s << (d ? d->prefix : defaulted_type::decoration().prefix);
s << v.first;
s << (d ? d->delimiter : defaulted_type::decoration().delimiter);
s << v.second;
s << (d ? d->postfix : defaulted_type::decoration().postfix);
return s;
}
template<class T, class CharT = char,
class TraitT = std::char_traits < CharT >>
typename std::enable_if < pretty::detail::is_range<T>::value,
std::basic_ostream < CharT, TraitT >> ::type & operator<< (
std::basic_ostream<CharT, TraitT> &s, T const & v)
{
bool first(true);
using deco_type = pretty::decor<T, CharT, TraitT>;
using default_type = pretty::defaulted<T, CharT, TraitT>;
void const * const p = s.pword(deco_type::xindex);
auto d = static_cast<pretty::decor<T, CharT, TraitT> const * const>(p);
s << (d ? d->prefix : default_type::decoration().prefix);
for (auto const & e : v)
{ // v is range thus range based for works
if (!first) s << (d ? d->delimiter : default_type::decoration().delimiter);
s << e;
first = false;
}
s << (d ? d->postfix : default_type::decoration().postfix);
return s;
}
#endif // pretty_print_0x57547_sa4884X_0_1_h_guard_
template<typename OutStream, typename T>
OutStream& operator<< (OutStream& out, const vector<T>& v)
{
for (auto const& tmp : v)
out << tmp << " ";
out << endl;
return out;
}
vector <int> test {1,2,3};
wcout << test; // or any output stream
for (auto i = path.cbegin(); i != path.cend(); ++i)
std::cout << *i << ' ';
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
template <typename T>
void print_contents(const std::vector<T>& v, const char * const separator = " ")
{
if(!v.empty())
{
std::copy(v.begin(),
--v.end(),
std::ostream_iterator<T>(std::cout, separator));
std::cout << v.back() << "\n";
}
}
// example usage
int main() {
std::vector<int> v{1, 2, 3, 4};
print_contents(v); // '1 2 3 4'
print_contents(v, ":"); // '1:2:3:4'
v = {};
print_contents(v); // ... no std::cout
v = {1};
print_contents(v); // '1'
return 0;
}
// includes and 'print_contents(...)' as above ...
class Foo
{
int i;
friend std::ostream& operator<<(std::ostream& out, const Foo& obj);
public:
Foo(const int i) : i(i) {}
};
std::ostream& operator<<(std::ostream& out, const Foo& obj)
{
return out << "foo_" << obj.i;
}
int main() {
std::vector<Foo> v{1, 2, 3, 4};
print_contents(v); // 'foo_1 foo_2 foo_3 foo_4'
print_contents(v, ":"); // 'foo_1:foo_2:foo_3:foo_4'
v = {};
print_contents(v); // ... no std::cout
v = {1};
print_contents(v); // 'foo_1'
return 0;
}
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
#include <vector>
#include <fmt/ranges.h>
int main() {
auto v = std::vector<int>{1, 2, 3};
fmt::print("{}", v);
}
{1, 2, 3}
template <typename T>
inline constexpr bool is_string_type_v = std::is_convertible_v<const T&, std::string_view>;
template<class T>
struct range_out {
range_out(T& range) : r_(range) {
}
T& r_;
static_assert(!::is_string_type_v<T>, "strings and string-like types should use operator << directly");
};
template <typename T>
std::ostream& operator<< (std::ostream& out, range_out<T>& range) {
constexpr bool is_string_like = is_string_type_v<T::value_type>;
constexpr std::string_view sep{ is_string_like ? "', '" : ", " };
if (!range.r_.empty()) {
out << (is_string_like ? "['" : "[");
out << *range.r_.begin();
for (auto it = range.r_.begin() + 1; it != range.r_.end(); ++it) {
out << sep << *it;
}
out << (is_string_like ? "']" : "]");
}
else {
out << "[]";
}
return out;
}
std::cout << range_out{ my_vector };
std::vector<char> test { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0' };
std::cout << test.data() << std::endl;
template <typename T>std::ostream& operator<< (std::ostream& out, std::vector<T>& v)
{
v.push_back('\0'); // safety-check!
out << v.data();
return out;
}
std::cout << test << std::endl; // will print 'Hello, world!'
fprintf(stdout, "%s\n", &test[0]); // will also print 'Hello, world!'
/*! \file print.hpp
* \brief Useful functions for work with STL containers.
*
* Now it supports generic print for STL containers like: [elem1, elem2, elem3]
* Supported STL conrainers: vector, deque, list, set multiset, unordered_set,
* map, multimap, unordered_map, array
*
* \author Skident
* \date 02.09.2016
* \copyright Skident Inc.
*/
#pragma once
// check is the C++11 or greater available (special hack for MSVC)
#if (defined(_MSC_VER) && __cplusplus >= 199711L) || __cplusplus >= 201103L
#define MODERN_CPP_AVAILABLE 1
#endif
#include <iostream>
#include <sstream>
#include <vector>
#include <deque>
#include <set>
#include <list>
#include <map>
#include <cctype>
#ifdef MODERN_CPP_AVAILABLE
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <forward_list>
#endif
#define dump(value) std::cout << (#value) << ": " << (value) << std::endl
#define BUILD_CONTENT \
std::stringstream ss; \
for (; it != collection.end(); ++it) \
{ \
ss << *it << elem_separator; \
} \
#define BUILD_MAP_CONTENT \
std::stringstream ss; \
for (; it != collection.end(); ++it) \
{ \
ss << it->first \
<< keyval_separator \
<< it->second \
<< elem_separator; \
} \
#define COMPILE_CONTENT \
std::string data = ss.str(); \
if (!data.empty() && !elem_separator.empty()) \
data = data.substr(0, data.rfind(elem_separator)); \
std::string result = first_bracket + data + last_bracket; \
os << result; \
if (needEndl) \
os << std::endl; \
////
///
///
/// Template definitions
///
///
//generic template for classes: deque, list, forward_list, vector
#define VECTOR_AND_CO_TEMPLATE \
template< \
template<class T, \
class Alloc = std::allocator<T> > \
class Container, class Type, class Alloc> \
#define SET_TEMPLATE \
template< \
template<class T, \
class Compare = std::less<T>, \
class Alloc = std::allocator<T> > \
class Container, class T, class Compare, class Alloc> \
#define USET_TEMPLATE \
template< \
template < class Key, \
class Hash = std::hash<Key>, \
class Pred = std::equal_to<Key>, \
class Alloc = std::allocator<Key> \
> \
class Container, class Key, class Hash, class Pred, class Alloc \
> \
#define MAP_TEMPLATE \
template< \
template<class Key, \
class T, \
class Compare = std::less<Key>, \
class Alloc = std::allocator<std::pair<const Key,T> > \
> \
class Container, class Key, \
class Value/*, class Compare, class Alloc*/> \
#define UMAP_TEMPLATE \
template< \
template<class Key, \
class T, \
class Hash = std::hash<Key>, \
class Pred = std::equal_to<Key>, \
class Alloc = std::allocator<std::pair<const Key,T> >\
> \
class Container, class Key, class Value, \
class Hash, class Pred, class Alloc \
> \
#define ARRAY_TEMPLATE \
template< \
template<class T, std::size_t N> \
class Array, class Type, std::size_t Size> \
namespace eos
{
static const std::string default_elem_separator = ", ";
static const std::string default_keyval_separator = " => ";
static const std::string default_first_bracket = "[";
static const std::string default_last_bracket = "]";
//! Prints template Container<T> as in Python
//! Supported containers: vector, deque, list, set, unordered_set(C++11), forward_list(C++11)
//! \param collection which should be printed
//! \param elem_separator the separator which will be inserted between elements of collection
//! \param first_bracket data before collection's elements (usual it is the parenthesis, square or curly bracker '(', '[', '{')
//! \param last_bracket data after collection's elements (usual it is the parenthesis, square or curly bracker ')', ']', '}')
template<class Container>
void print( const Container& collection
, const std::string& elem_separator = default_elem_separator
, const std::string& first_bracket = default_first_bracket
, const std::string& last_bracket = default_last_bracket
, std::ostream& os = std::cout
, bool needEndl = true
)
{
typename Container::const_iterator it = collection.begin();
BUILD_CONTENT
COMPILE_CONTENT
}
//! Prints collections with one template argument and allocator as in Python.
//! Supported standard collections: vector, deque, list, forward_list
//! \param collection which should be printed
//! \param elem_separator the separator which will be inserted between elements of collection
//! \param keyval_separator separator between key and value of map. For default it is the '=>'
//! \param first_bracket data before collection's elements (usual it is the parenthesis, square or curly bracker '(', '[', '{')
//! \param last_bracket data after collection's elements (usual it is the parenthesis, square or curly bracker ')', ']', '}')
VECTOR_AND_CO_TEMPLATE
void print( const Container<Type>& collection
, const std::string& elem_separator = default_elem_separator
, const std::string& first_bracket = default_first_bracket
, const std::string& last_bracket = default_last_bracket
, std::ostream& os = std::cout
, bool needEndl = true
)
{
typename Container<Type>::const_iterator it = collection.begin();
BUILD_CONTENT
COMPILE_CONTENT
}
//! Prints collections like std:set<T, Compare, Alloc> as in Python
//! \param collection which should be printed
//! \param elem_separator the separator which will be inserted between elements of collection
//! \param keyval_separator separator between key and value of map. For default it is the '=>'
//! \param first_bracket data before collection's elements (usual it is the parenthesis, square or curly bracker '(', '[', '{')
//! \param last_bracket data after collection's elements (usual it is the parenthesis, square or curly bracker ')', ']', '}')
SET_TEMPLATE
void print( const Container<T, Compare, Alloc>& collection
, const std::string& elem_separator = default_elem_separator
, const std::string& first_bracket = default_first_bracket
, const std::string& last_bracket = default_last_bracket
, std::ostream& os = std::cout
, bool needEndl = true
)
{
typename Container<T, Compare, Alloc>::const_iterator it = collection.begin();
BUILD_CONTENT
COMPILE_CONTENT
}
//! Prints collections like std:unordered_set<Key, Hash, Pred, Alloc> as in Python
//! \param collection which should be printed
//! \param elem_separator the separator which will be inserted between elements of collection
//! \param keyval_separator separator between key and value of map. For default it is the '=>'
//! \param first_bracket data before collection's elements (usual it is the parenthesis, square or curly bracker '(', '[', '{')
//! \param last_bracket data after collection's elements (usual it is the parenthesis, square or curly bracker ')', ']', '}')
USET_TEMPLATE
void print( const Container<Key, Hash, Pred, Alloc>& collection
, const std::string& elem_separator = default_elem_separator
, const std::string& first_bracket = default_first_bracket
, const std::string& last_bracket = default_last_bracket
, std::ostream& os = std::cout
, bool needEndl = true
)
{
typename Container<Key, Hash, Pred, Alloc>::const_iterator it = collection.begin();
BUILD_CONTENT
COMPILE_CONTENT
}
//! Prints collections like std:map<T, U> as in Python
//! supports generic objects of std: map, multimap
//! \param collection which should be printed
//! \param elem_separator the separator which will be inserted between elements of collection
//! \param keyval_separator separator between key and value of map. For default it is the '=>'
//! \param first_bracket data before collection's elements (usual it is the parenthesis, square or curly bracker '(', '[', '{')
//! \param last_bracket data after collection's elements (usual it is the parenthesis, square or curly bracker ')', ']', '}')
MAP_TEMPLATE
void print( const Container<Key, Value>& collection
, const std::string& elem_separator = default_elem_separator
, const std::string& keyval_separator = default_keyval_separator
, const std::string& first_bracket = default_first_bracket
, const std::string& last_bracket = default_last_bracket
, std::ostream& os = std::cout
, bool needEndl = true
)
{
typename Container<Key, Value>::const_iterator it = collection.begin();
BUILD_MAP_CONTENT
COMPILE_CONTENT
}
//! Prints classes like std:unordered_map as in Python
//! \param collection which should be printed
//! \param elem_separator the separator which will be inserted between elements of collection
//! \param keyval_separator separator between key and value of map. For default it is the '=>'
//! \param first_bracket data before collection's elements (usual it is the parenthesis, square or curly bracker '(', '[', '{')
//! \param last_bracket data after collection's elements (usual it is the parenthesis, square or curly bracker ')', ']', '}')
UMAP_TEMPLATE
void print( const Container<Key, Value, Hash, Pred, Alloc>& collection
, const std::string& elem_separator = default_elem_separator
, const std::string& keyval_separator = default_keyval_separator
, const std::string& first_bracket = default_first_bracket
, const std::string& last_bracket = default_last_bracket
, std::ostream& os = std::cout
, bool needEndl = true
)
{
typename Container<Key, Value, Hash, Pred, Alloc>::const_iterator it = collection.begin();
BUILD_MAP_CONTENT
COMPILE_CONTENT
}
//! Prints collections like std:array<T, Size> as in Python
//! \param collection which should be printed
//! \param elem_separator the separator which will be inserted between elements of collection
//! \param keyval_separator separator between key and value of map. For default it is the '=>'
//! \param first_bracket data before collection's elements (usual it is the parenthesis, square or curly bracker '(', '[', '{')
//! \param last_bracket data after collection's elements (usual it is the parenthesis, square or curly bracker ')', ']', '}')
ARRAY_TEMPLATE
void print( const Array<Type, Size>& collection
, const std::string& elem_separator = default_elem_separator
, const std::string& first_bracket = default_first_bracket
, const std::string& last_bracket = default_last_bracket
, std::ostream& os = std::cout
, bool needEndl = true
)
{
typename Array<Type, Size>::const_iterator it = collection.begin();
BUILD_CONTENT
COMPILE_CONTENT
}
//! Removes all whitespaces before data in string.
//! \param str string with data
//! \return string without whitespaces in left part
std::string ltrim(const std::string& str);
//! Removes all whitespaces after data in string
//! \param str string with data
//! \return string without whitespaces in right part
std::string rtrim(const std::string& str);
//! Removes all whitespaces before and after data in string
//! \param str string with data
//! \return string without whitespaces before and after data in string
std::string trim(const std::string& str);
////////////////////////////////////////////////////////////
////////////////////////ostream logic//////////////////////
/// Should be specified for concrete containers
/// because of another types can be suitable
/// for templates, for example templates break
/// the code like this "cout << string("hello") << endl;"
////////////////////////////////////////////////////////////
#define PROCESS_VALUE_COLLECTION(os, collection) \
print( collection, \
default_elem_separator, \
default_first_bracket, \
default_last_bracket, \
os, \
false \
); \
#define PROCESS_KEY_VALUE_COLLECTION(os, collection) \
print( collection, \
default_elem_separator, \
default_keyval_separator, \
default_first_bracket, \
default_last_bracket, \
os, \
false \
); \
///< specialization for vector
template<class T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
///< specialization for deque
template<class T>
std::ostream& operator<<(std::ostream& os, const std::deque<T>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
///< specialization for list
template<class T>
std::ostream& operator<<(std::ostream& os, const std::list<T>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
///< specialization for set
template<class T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
///< specialization for multiset
template<class T>
std::ostream& operator<<(std::ostream& os, const std::multiset<T>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
#ifdef MODERN_CPP_AVAILABLE
///< specialization for unordered_map
template<class T>
std::ostream& operator<<(std::ostream& os, const std::unordered_set<T>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
///< specialization for forward_list
template<class T>
std::ostream& operator<<(std::ostream& os, const std::forward_list<T>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
///< specialization for array
template<class T, std::size_t N>
std::ostream& operator<<(std::ostream& os, const std::array<T, N>& collection)
{
PROCESS_VALUE_COLLECTION(os, collection)
return os;
}
#endif
///< specialization for map, multimap
MAP_TEMPLATE
std::ostream& operator<<(std::ostream& os, const Container<Key, Value>& collection)
{
PROCESS_KEY_VALUE_COLLECTION(os, collection)
return os;
}
///< specialization for unordered_map
UMAP_TEMPLATE
std::ostream& operator<<(std::ostream& os, const Container<Key, Value, Hash, Pred, Alloc>& collection)
{
PROCESS_KEY_VALUE_COLLECTION(os, collection)
return os;
}
}
std::string s1 = "s1: " + std::to_string(arr) + "; " + std::to_string(vec) + "; " + std::to_string(tup);
std::string s2 = STR() << "s2: " << arr << "; " << vec << "; " << tup;
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <array>
namespace std
{
// declations: needed for std::to_string(std::vector<std::tuple<int, float>>)
std::string to_string(std::string str);
std::string to_string(const char *str);
template<typename T, size_t N>
std::string to_string(std::array<T, N> const& arr);
template<typename T>
std::string to_string(std::vector<T> const& vec);
template<typename... Args>
std::string to_string(const std::tuple<Args...>& tup);
std::string to_string(std::string str)
{
return std::string(str);
}
std::string to_string(const char *str)
{
return std::string(str);
}
template<typename T, size_t N>
std::string to_string(std::array<T, N> const& arr)
{
std::string s="{";
for (std::size_t t = 0; t != N; ++t)
s += std::to_string(arr[t]) + (t+1 < N ? ", ":"");
return s + "}";
}
template<typename T>
std::string to_string(std::vector<T> const& vec)
{
std::string s="[";
for (std::size_t t = 0; t != vec.size(); ++t)
s += std::to_string(vec[t]) + (t+1 < vec.size() ? ", ":"");
return s + "]";
}
// to_string(tuple)
// https://en.cppreference.com/w/cpp/utility/tuple/operator%3D
template<class Tuple, std::size_t N>
struct TupleString
{
static std::string str(const Tuple& tup)
{
std::string out;
out += TupleString<Tuple, N-1>::str(tup);
out += ", ";
out += std::to_string(std::get<N-1>(tup));
return out;
}
};
template<class Tuple>
struct TupleString<Tuple, 1>
{
static std::string str(const Tuple& tup)
{
std::string out;
out += std::to_string(std::get<0>(tup));
return out;
}
};
template<typename... Args>
std::string to_string(const std::tuple<Args...>& tup)
{
std::string out = "(";
out += TupleString<decltype(tup), sizeof...(Args)>::str(tup);
out += ")";
return out;
}
} // namespace std
/**
* cout: cout << continer
*/
template <typename T, std::size_t N> // cout << array
std::ostream& operator <<(std::ostream &out, std::array<T, N> &con)
{
out << std::to_string(con);
return out;
}
template <typename T, typename A> // cout << vector
std::ostream& operator <<(std::ostream &out, std::vector<T, A> &con)
{
out << std::to_string(con);
return out;
}
template<typename... Args> // cout << tuple
std::ostream& operator <<(std::ostream &out, std::tuple<Args...> &con)
{
out << std::to_string(con);
return out;
}
/**
* Concatenate: string << continer
*/
template <class C>
std::string operator <<(std::string str, C &con)
{
std::string out = str;
out += std::to_string(con);
return out;
}
#define STR() std::string("")
int main()
{
std::array<int, 3> arr {1, 2, 3};
std::string sArr = std::to_string(arr);
std::cout << "std::array" << std::endl;
std::cout << "\ttest to_string: " << sArr << std::endl;
std::cout << "\ttest cout <<: " << arr << std::endl;
std::cout << "\ttest string <<: " << (std::string() << arr) << std::endl;
std::vector<std::string> vec {"a", "b"};
std::string sVec = std::to_string(vec);
std::cout << "std::vector" << std::endl;
std::cout << "\ttest to_string: " << sVec << std::endl;
std::cout << "\ttest cout <<: " << vec << std::endl;
std::cout << "\ttest string <<: " << (std::string() << vec) << std::endl;
std::tuple<int, std::string> tup = std::make_tuple(5, "five");
std::string sTup = std::to_string(tup);
std::cout << "std::tuple" << std::endl;
std::cout << "\ttest to_string: " << sTup << std::endl;
std::cout << "\ttest cout <<: " << tup << std::endl;
std::cout << "\ttest string <<: " << (std::string() << tup) << std::endl;
std::vector<std::tuple<int, float>> vt {std::make_tuple(1, .1), std::make_tuple(2, .2)};
std::string sVt = std::to_string(vt);
std::cout << "std::vector<std::tuple>" << std::endl;
std::cout << "\ttest to_string: " << sVt << std::endl;
std::cout << "\ttest cout <<: " << vt << std::endl;
std::cout << "\ttest string <<: " << (std::string() << vt) << std::endl;
std::cout << std::endl;
std::string s1 = "s1: " + std::to_string(arr) + "; " + std::to_string(vec) + "; " + std::to_string(tup);
std::cout << s1 << std::endl;
std::string s2 = STR() << "s2: " << arr << "; " << vec << "; " << tup;
std::cout << s2 << std::endl;
return 0;
}
std::array
test to_string: {1, 2, 3}
test cout <<: {1, 2, 3}
test string <<: {1, 2, 3}
std::vector
test to_string: [a, b]
test cout <<: [a, b]
test string <<: [a, b]
std::tuple
test to_string: (5, five)
test cout <<: (5, five)
test string <<: (5, five)
std::vector<std::tuple>
test to_string: [(1, 0.100000), (2, 0.200000)]
test cout <<: [(1, 0.100000), (2, 0.200000)]
test string <<: [(1, 0.100000), (2, 0.200000)]
s1: {1, 2, 3}; [a, b]; (5, five)
s2: {1, 2, 3}; [a, b]; (5, five)
#include <boost/algorithm/string/join.hpp>
std::vector<std::string> vs { "some", "string", "vector" };
std::cout << boost::algorithm::join(vs, " | ") << '\n';
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>
int main()
{
using boost::adaptors::transformed;
using boost::algorithm::join;
// Generate the vector
std::vector<int> vi(10);
std::iota(vi.begin(), vi.end(), -3);
// Print out the vector
std::cout << join(vi |
transformed(static_cast<std::string(*)(int)>(std::to_string)),
", ")
<< '\n';
}