#include <iostream>
#include <vector>
#include <list>
#include <boost/range.hpp>
using namespace std;
template<typename...> struct void_ { using type = void; };
template<typename... T> using Void = typename void_<T...>::type;
template<typename... T> using BoostRangeValue = typename boost::range_value<T...>::type;
//////////////////
template<typename T, typename Sfinae = void>
struct range_value {};
template<typename T>
struct range_value<T, Void<BoostRangeValue<T>>>: BoostRangeValue<T> {};
template<typename... T> using RangeValue = typename range_value<T...>::type;
//////////////////
template <typename T, typename C>
typename enable_if<std::is_same<T, RangeValue<C>>::value, C>::type
concat(C c, T v)
{
c.insert(end(c), v);
return c;
}
template <typename R, typename C>
typename enable_if<
std::is_same< RangeValue<R>, RangeValue<C>
>::value, C>::type
concat(C c, R const& r)
{
c.insert(end(c), begin(r), end(r));
return c;
}
//////////////////
// THIS IS CHEATING...
// template<> struct range_value<int, void> {};
//////////////////
int main()
{
auto v = concat(vector<int> { 1,2,3 }, list<int> { 4,5,6 });
for(auto i : v)
std::cout << i << " ";
// does not SFINAE?
v = concat(vector<int> { 1,2,3 }, 42);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bGlzdD4KI2luY2x1ZGUgPGJvb3N0L3JhbmdlLmhwcD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgp0ZW1wbGF0ZTx0eXBlbmFtZS4uLj4gc3RydWN0IHZvaWRfIHsgdXNpbmcgdHlwZSA9IHZvaWQ7IH07CnRlbXBsYXRlPHR5cGVuYW1lLi4uIFQ+IHVzaW5nIFZvaWQgPSB0eXBlbmFtZSB2b2lkXzxULi4uPjo6dHlwZTsKCnRlbXBsYXRlPHR5cGVuYW1lLi4uIFQ+IHVzaW5nIEJvb3N0UmFuZ2VWYWx1ZSA9IHR5cGVuYW1lIGJvb3N0OjpyYW5nZV92YWx1ZTxULi4uPjo6dHlwZTsKCi8vLy8vLy8vLy8vLy8vLy8vLwp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBTZmluYWUgPSB2b2lkPgpzdHJ1Y3QgcmFuZ2VfdmFsdWUge307Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgcmFuZ2VfdmFsdWU8VCwgVm9pZDxCb29zdFJhbmdlVmFsdWU8VD4+PjogQm9vc3RSYW5nZVZhbHVlPFQ+IHt9OwoKdGVtcGxhdGU8dHlwZW5hbWUuLi4gVD4gdXNpbmcgUmFuZ2VWYWx1ZSA9IHR5cGVuYW1lIHJhbmdlX3ZhbHVlPFQuLi4+Ojp0eXBlOwovLy8vLy8vLy8vLy8vLy8vLy8KCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBDPgogICAgdHlwZW5hbWUgZW5hYmxlX2lmPHN0ZDo6aXNfc2FtZTxULCBSYW5nZVZhbHVlPEM+Pjo6dmFsdWUsIEM+Ojp0eXBlIAogICAgY29uY2F0KEMgYywgVCB2KQp7CiAgICBjLmluc2VydChlbmQoYyksIHYpOwogICAgcmV0dXJuIGM7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBSLCB0eXBlbmFtZSBDPgogICAgdHlwZW5hbWUgZW5hYmxlX2lmPAogICAgICAgIHN0ZDo6aXNfc2FtZTwgUmFuZ2VWYWx1ZTxSPiwgUmFuZ2VWYWx1ZTxDPgogICAgICAgID46OnZhbHVlLCBDPjo6dHlwZSAKICAgIGNvbmNhdChDIGMsIFIgY29uc3QmIHIpCnsKICAgIGMuaW5zZXJ0KGVuZChjKSwgYmVnaW4ociksIGVuZChyKSk7CiAgICByZXR1cm4gYzsKfQoKLy8vLy8vLy8vLy8vLy8vLy8vCi8vIFRISVMgSVMgQ0hFQVRJTkcuLi4KLy8gdGVtcGxhdGU8PiBzdHJ1Y3QgcmFuZ2VfdmFsdWU8aW50LCB2b2lkPiB7fTsKCi8vLy8vLy8vLy8vLy8vLy8vLwppbnQgbWFpbigpCnsKICAgIGF1dG8gdiA9IGNvbmNhdCh2ZWN0b3I8aW50PiB7IDEsMiwzIH0sIGxpc3Q8aW50PiB7IDQsNSw2IH0pOwogICAgZm9yKGF1dG8gaSA6IHYpCiAgICAgICAgc3RkOjpjb3V0IDw8IGkgPDwgIiAiOwoKICAgIC8vIGRvZXMgbm90IFNGSU5BRT8KICAgIHYgPSBjb25jYXQodmVjdG9yPGludD4geyAxLDIsMyB9LCA0Mik7Cn0KCg==