Do one thing at a time:
template<class R>
R sort_the_range( R&& r ) {
using std::begin; using std::end;
std::sort( begin(r), end(r) );
return std::forward<R>(r);
}
some metaprogramming: (hana-style)
template<class T> struct tag{using type=T;};
template<class...> struct types{using type=types;};
template<class Tag>using type_t=typename Tag::type;
template<class Default, class...Ts,
class=typename std::enable_if<!std::is_same<void,Default>::value>::type
>
constexpr tag<Default> type_from( tag<Default>, Ts... ) { return {}; }
template<class T0, class...Ts>
constexpr tag<T0> type_from( tag<void>, tag<T0>, Ts... ) { return {}; }
template<class Default, class...Ts>
using type_from_t = type_t< decltype( type_from( tag<Default>{}, tag<Ts>{}... ) ) >;
now, a function that makes a vector. You can pass in a type for the vector, or have it deduce from the first argument, your choice:
// explicit T argument is optional:
template<class ExplicitType=void, class...Ts,
// deduce return type:
class R=type_from_t<ExplicitType, typename std::decay<Ts>::type...>
>
std::vector<R> make_vector( Ts&&... ts ) {
// block explicit conversions:
using test = decltype(std::array<R, sizeof...(Ts)>{{ std::declval<Ts>()... }});
(void)tag<test>{}; // block warnings
// make our vector, and size it right:
std::vector<R> retval;
retval.reserve( sizeof...(ts) );
// populate the vector:
(void)std::initializer_list<int>{0,((
retval.emplace_back(std::forward<Ts>(ts))
),void(),0)...};
return retval;
}
and stitch:
template<class T=void, class...Ts>
auto make_sorted_vector(Ts&&...ts)
->decltype( make_vector<T>(std::forward<Ts>(ts)...) )
{
return sort_the_range(
make_vector<T>( std::forward<Ts>(ts)... )
);
}
live example)