Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 869
sandthorn Avatar asked Jan 02 '18 12:01

sandthorn


1 Answers

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

like image 129
StoryTeller - Unslander Monica Avatar answered Nov 20 '22 16:11

StoryTeller - Unslander Monica