Last active
August 29, 2015 14:12
-
-
Save m00shm00sh/36d8bb80520ba8e15c0d to your computer and use it in GitHub Desktop.
Implementation of operator<< for containers which have insert or push_{back,front}
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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