Search code examples
c++templatesoverload-resolution

How to select the right overload of function template?


I'm using libcxx 16.0.0 from the LLVM project.

In __algorithm/fill_n.h, there is the following function:

// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.

template <class _OutputIterator, class _Size, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value)
{
    for (; __n > 0; ++__first, (void) --__n)
        *__first = __value;
    return __first;
}

The problem is that in my case the function is not optimized to std::memset. So I would like to do this specialization manually.

I was hoping to add an overload of __fil_n for trivially copyable _Tp and contiguous iterators (including std::array's iterator).

So, given the following code,

template <typename T, int N> struct foo_t {
  struct iterator {};
};

template <typename T> int f(T) { return 1; }

template <typename T, int N> int f(typename foo_t<T, N>::iterator) { return 2; }

int main() {
  foo_t<int, 10>::iterator a;

  return f(a);
}

How can I change the signatures of f so that the second overload is selected at the f function call in main ?

A solution with a C++ version >= 11 but <20 would be ideal.


Solution

  • with typename foo_t<T, N>::iterator, T and N are non deducible.

    friend function helps:

    template <typename T, int N>
    struct foo_t {
      struct iterator {
          friend int f(iterator) { return 2; } // f is no longer template
      };
    };
    
    template <typename T> int f(T) { return 1; }
    

    Demo