Search code examples
c++templatesc++17class-templateconstructor-overloading

Two identical constructors however compiler selects the templated one


I am trying to implement a list container in C++, and I have problem with compiler selecting the wrong constructor overload.

The constructors are as follows:

list(size_type count, const T& value);

template<typename InputIt>
list(InputIt begin, InputIt end);

When I initialize the object in the source file, I can not prevent the compiler from selecting the second overload:

list<int> x(5, 45);

The second overload should be selected when the given arguments are iterators. However, I can't accomplish it.


EDIT: The class declaration looks like this:

template<typename T, typename Allocator = std::allocator<T>> 
class list 
{
public:
    using value_type = T;
    using pointer = T*;
    using const_pointer = const T*;
    using reference = T&;
    using const_reference = const T&;
    using move_reference = T&&; // custom
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;

    list(size_type count, const T& value);

    template<typename InputIt>
    list(InputIt begin, InputIt end);
    // ...
};

Solution

  • The second overload should be selected when the given arguments are iterable however I can't accomplish it?

    You need to SFINAE ("Substitution Failure Is Not An Error") one of the constructors (prior to C++20), so that correct constructors will be chosen.

    // Constructor for iterator range
    template<typename InputIt
        , std::enable_if_t<
               std::is_constructible_v<
                   T, typename std::iterator_traits<InputIt>::value_type>>* = nullptr
               >
        list(InputIt begin, InputIt end)
        /* : contr init list */
    {}
    

    See live demo


    In C++20, however, just constrain the constructor for std::input_or_output_iterator:

    template<typename InputIt>
        requires (std::input_or_output_iterator<InputIt>)
    list(InputIt begin, InputIt end) 
      /* : contr init list */
    {}
    

    See live demo