简体   繁体   中英

How to constrain a parameter type to allow only std::initializer_list<size_t> or std::array<size_t, N>?

I would like to have only one template function. So I came up with like...

template<typename Iteratable, size_t N,
         typename = 
            std::enable_if_t<
                std::is_same_v<Iteratable, const std::initializer_list<size_t> > ||
                std::is_same_v<Iteratable, const std::array<size_t, N > >
            > 
>
std::ostream& operator << (std::ostream& os, Iteratable& in) {
    std::copy(std::begin(in), std::end(in), std::ostream_iterator<size_t>(os, " ") ); 
    return os;
}

It seems because of N in std::array<size_t, N> , the specialization fails.

Is there any how not to write 2 function for this use case?

If the sole reason you don't want to overload is to avoid duplicating the function body, you can instead go for writing your own trait. One such way:

namespace details {
  template<class Iterable>
  struct writable : std::false_type {};

  template<size_t N>
  struct writable<std::array<std::size_t, N>> : std::true_type {};

  template<>
  struct writable<std::initializer_list<size_t>> : std::true_type {};

  template<class Iterable>
  constexpr bool writable_v = writable<Iterable>::value;
}

template<typename Iteratable,
         std::enable_if_t<details::writable_v<std::decay_t<Iteratable>>,
         int> = 0 
>
std::ostream& operator << (std::ostream& os, Iteratable& in) {
    std::copy(std::begin(in), std::end(in), std::ostream_iterator<size_t>(os, " ") ); 
    return os;
}

I also took the liberty of moving the enable_if to the template argument. That way SFINAE cannot be circumvented by specifying a type name for both arguments (though admittedly, it's unlikely to happen for an overloaded operator).

Another nice fact about it is that the customization point is now decoupled from the function definition itself. Adding new iterables is just a matter of adding another specialization for details::writable .

Live Example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM