I have defined a type that acts as an integer. I want to define a specialization for std::common\_type for my type. However, this specialization should be able to give the common\_type of bounded\_integer (my class) in combination with any number of other arguments that are either other bounded\_integer or built-in integer types. I want the following code to all be valid:

```
std::common_type<bounded_integer<1, 10>>::type
std::common_type<bounded_integer<1, 10>, int>::type
std::common_type<int, long, bounded_integer<1, 10>>::type
std::common_type<int, int, long, short, long long, short, bounded_integer<1, 10>, int, short, short, short, ..., short, bounded_integer<1, 10>>::type

```

My first attempt at solving this problem was by using enable\_if. However, I realized that this would not allow me to distinguish from the library definition of common\_type, as what I had was essentially

```
#include <type_traits>

class C {};

template<typename T, typename... Ts>
class contains_c {
public:
        static constexpr bool value = contains_c<T>::value or contains_c<Ts...>::value;
};
template<typename T>
class contains_c<T> {
public:
        static constexpr bool value = std::is_same<T, C>::value;
};

namespace std {

template<typename... Args, typename std::enable_if<contains_c<Args...>::value>::type>
class common_type<Args...> {
public:
        using type = C;
};

}       // namespace std

int main() {
}

```

Where the 'partial specialization' is really just "any arguments", which is no more specialized than what we have.

So it seems like the only solution is to require my users to do one of the following:

1. always put the bounded\_integer as the first argument to common\_type
2. always use my make\_bounded(built-in integer value) function to convert their integers to bounded\_integer (so don't have a specialization of common\_type for built-in types in combination with bounded\_integer)
3. never put bounded\_integer in a position greater than N, where N is some number I determine, similar to Visual Studio's old variadic template work-around

3 would look something like this:

```
// all_bounded_integer_or_integral and all_are_integral defined elsewhere with obvious definitions
template<intmax_t minimum, intmax_t maximum, typename... Ts, typename = type std::enable_if<all_bounded_integer_or_integral<Ts...>::value>::type>
class common_type<bounded_integer<minimum, maximum>, Ts...> {
};
template<typename T1, intmax_t minimum, intmax_t maximum, typename... Ts, typename = typename std::enable_if<all_are_integral<T1>::value>::type, typename = typename std::enable_if<all_bounded_integer_or_builtin<Ts...>::value>::type>
class common_type<T1, bounded_integer<minimum, maximum>, Ts...> {
};
template<typename T1, typename T2, intmax_t minimum, intmax_t maximum, typename... Ts, typename = typename std::enable_if<all_are_integral<T1, T2>::value>::type, typename = typename std::enable_if<all_bounded_integer_or_builtin<Ts...>::value>::type>
class common_type<T1, T2, bounded_integer<minimum, maximum>, Ts...> {
};
// etc.

```

Is there a better way to accomplish this (template specialization when all the types meet one condition and any of the types meet another condition) for a class that I cannot change the original definition for?

EDIT:

Based on the answers, I was not clear enough in my problem.

First, expected behavior:

If someone calls std::common\_type with all of the types being an instance of bounded\_integer or a built-in numeric type, I want the result to be a bounded\_integer that has a minimum of all of the possible minimums and a maximum of all of the possible maximums.

The problem:

I have a working solution when someone calls std::common\_type on any number of bounded\_integer. However, if I only specialize the two-argument version, then I run into the following problem:

`std::common_type<int, unsigned, bounded_integer<0, std::numeric_limits<unsigned>::max() + 1>`

should give me

`bounded_integer<std::numeric_limits<int>::min(), std::numeric_limits<unsigned>::max() + 1>`

However, it does not. It first applies common\_type to `int` and `unsigned`, which follows the standard integral promotion rules, giving `unsigned`. Then it returns the result of `common_type` with `unsigned` and my `bounded_integer`, giving

`bounded_integer<0, std::numeric_limits<unsigned>::max() + 1>`

So by adding `unsigned` to the middle of the parameter pack, even though it should have absolutely no impact on the result type (its ranges are entirely contained within the ranges of all other types), it still affects the result. The only way I can think of to prevent this is to specialize `std::common_type` for any number of built-in integers followed by `bounded_integer`, followed by any number of built-in integers or `bounded_integer`.

My question is: how can I do this without having to approximate it by manually writing out an arbitrary number of parameters followed by a `bounded_integer` followed by a parameter pack, or is this not possible?

EDIT 2:

The reason that common\_type will give the wrong values can be explained by this reasoning following the standard (quoting from N3337)

The `common_type` of `int` and `unsigned` is `unsigned`. For an example: <http://ideone.com/9IxKIW> . Standardese can be found in § 20.9.7.6/3, where the `common_type` of two values is

`typedef decltype(true ? declval<T>() : declval<U>()) type;`

In § 5.16/6, it says

> 
> The second and third operands have arithmetic or enumeration type; the
>  usual arithmetic conversions are performed to bring them to a common
>  type, and the result is of that type.
> 
> 
> 

The usual arithmetic conversions are defined in § 5/9 as

> 
> Otherwise, if the operand that has unsigned integer type has rank
>  greater than or equal to the rank of the type of the other operand,
>  the operand with signed integer type shall be converted to the type of
>  the operand with unsigned integer type.
> 
> 
>