Also is it possible to remove duplicates while we are performing the sort check, in this case I am fine if we stop removing duplicates as soon as templates detect that sequence is not sorted.
Yes, it's possible.
Maybe can be done a little simpler, but... using and abusing template specialization...
Given an helper class as the following
// csardh: check sort and remove duplicates helper
template <typename T, typename>
struct csardh
{ using type = T; };
template <typename T, T ... ordered, T v0, T v1, T ... vs>
struct csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0, v1, vs...>>
: public std::conditional_t<
(v0 < v1),
csardh<std::integer_sequence<T, ordered..., v0>,
std::integer_sequence<T, v1, vs...>>,
csardh<std::integer_sequence<T, ordered..., v0, v1, vs...>, void>>
{ };
template <typename T, T ... ordered, T v0, T ... vs>
struct csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0, v0, vs...>>
: public csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0, vs...>>
{ };
template <typename T, T ... ordered, T v0>
struct csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0>>
: public csardh<std::integer_sequence<T, ordered..., v0>, void>
{ };
the main class become
// csard: check sort and remove duplicates
template <typename>
struct csard;
template <typename T, T... vals>
struct csard<std::integer_sequence<T, vals...>>
: public csardh<std::integer_sequence<T>,
std::integer_sequence<T, vals...>>
{ };
A using can be useful to simplify the use
template <typename T>
using csard_t = typename csard<T>::type;
The following is a full compiling example (C++14 is enough)
#include <utility>
#include <type_traits>
// csardh: check sort and remove duplicates helper
template <typename T, typename>
struct csardh
{ using type = T; };
template <typename T, T ... ordered, T v0, T v1, T ... vs>
struct csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0, v1, vs...>>
: public std::conditional_t<
(v0 < v1),
csardh<std::integer_sequence<T, ordered..., v0>,
std::integer_sequence<T, v1, vs...>>,
csardh<std::integer_sequence<T, ordered..., v0, v1, vs...>, void>>
{ };
template <typename T, T ... ordered, T v0, T ... vs>
struct csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0, v0, vs...>>
: public csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0, vs...>>
{ };
template <typename T, T ... ordered, T v0>
struct csardh<std::integer_sequence<T, ordered...>,
std::integer_sequence<T, v0>>
: public csardh<std::integer_sequence<T, ordered..., v0>, void>
{ };
// csard: check sort and remove duplicates
template <typename>
struct csard;
template <typename T, T... vals>
struct csard<std::integer_sequence<T, vals...>>
: public csardh<std::integer_sequence<T>,
std::integer_sequence<T, vals...>>
{ };
template <typename T>
using csard_t = typename csard<T>::type;
int main()
{
using T0 = std::integer_sequence<int,4,4,4,5,5,3,2,2,1>;
using T1 = csard_t<T0>;
using T2 = std::integer_sequence<int,4,5,3,2,2,1>;
static_assert( std::is_same<T1, T2>::value, "!" );
using U0 = std::integer_sequence<int,1,2,3,4>;
using U1 = csard_t<U0>;
using U2 = U0;
static_assert( std::is_same<U1, U2>::value, "!" );
using V0 = std::integer_sequence<int,1,2,2,3,4>;
using V1 = csard_t<V0>;
using V2 = U2;
static_assert( std::is_same<V1, V2>::value, "!" );
}