Skip to content

Instantly share code, notes, and snippets.

@m00shm00sh
Last active August 29, 2015 14:12
Show Gist options
  • Save m00shm00sh/36d8bb80520ba8e15c0d to your computer and use it in GitHub Desktop.
Save m00shm00sh/36d8bb80520ba8e15c0d to your computer and use it in GitHub Desktop.
Implementation of operator<< for containers which have insert or push_{back,front}
#if __cplusplus < 201103L
#error "missing -std=c++11"
#endif
#include <utility>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <forward_list>
#include <deque>
#include <type_traits>
#include <boost/tti/has_member_function.hpp>
#include "prettyprint.hpp"
BOOST_TTI_HAS_MEMBER_FUNCTION(insert)
BOOST_TTI_HAS_MEMBER_FUNCTION(push_back)
BOOST_TTI_HAS_MEMBER_FUNCTION(push_front)
template <typename C>
constexpr bool has_push_back() {
return has_member_function_push_back<C, void, boost::mpl::vector<typename C::value_type const&>>::value;
}
template <typename C>
constexpr bool has_push_back_r() {
return has_member_function_push_back<C, void, boost::mpl::vector<typename C::value_type&&>>::value;
}
template <typename C>
constexpr bool has_push_front() {
return has_member_function_push_front<C, void, boost::mpl::vector<typename C::value_type const&>>::value
&& !has_push_back<C>();
}
template <typename C>
constexpr bool has_push_front_r() {
return has_member_function_push_front<C, void, boost::mpl::vector<typename C::value_type&&>>::value
&& !has_push_back_r<C>();
}
template <typename C>
constexpr bool has_insert() {
return has_member_function_insert<C, std::pair<typename C::iterator, bool>,
boost::mpl::vector<typename C::value_type const&>
>::value;
}
template <typename C>
constexpr bool has_insert_r() {
return has_member_function_insert<C, std::pair<typename C::iterator, bool>,
boost::mpl::vector<typename C::value_type&&>
>::value;
}
template <typename C, typename>
constexpr bool is_possible() {
return has_push_back_r<C>() || has_push_front_r<C>() || has_insert_r<C>();
}
template <typename C, typename>
constexpr bool is_possible() {
return has_push_back<C>() || has_push_front<C>() || has_insert<C>();
}
// forward_list
template <typename C>
typename std::enable_if<has_push_front<C>()>::type
do_add(C& c, typename C::value_type const& v)
{
c.push_front(v);
}
// vector, deque, etc
template <typename C>
typename std::enable_if<has_push_back<C>()>::type
do_add(C& c, typename C::value_type const& v)
{
c.push_back(v);
}
template <typename C>
typename std::enable_if<has_insert<C>()>::type
do_add(C& c, typename C::value_type const& v)
{
c.insert(v);
}
template <typename C, typename V = typename C::value_type>>
auto possible() -> typename std::enable_if<is_possible<C,V>(), C>::type;
template <typename C>
auto operator<<= (C& c, typename C::value_type const& v) -> decltype(possible<C>())& {
do_add(c, v);
return c;
}
template <typename C>
auto operator<< (C c, typename C::value_type const& v) -> decltype(possible<C>()) {
do_add(c, v);
return c;
}
int main(){
std::vector<int> vi;
std::forward_list<int> fi;
std::list<int> li;
std::set<int> si;
std::map<int,int> mi;
vi <<= 1;
fi <<= 2;
li <<= 3;
si <<= 4;
mi <<= std::make_pair(5,6);
std::cout<<vi<<'\n'
<<fi<<'\n'
<<li<<'\n'
<<si<<'\n'
<<mi<<'\n'
<<std::flush;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment