forward_list: assign(_InputIterator __first, _InputIterator __last) / assign(size_type __n, const _Tp& __val)

前端 未结 2 1949
遇见更好的自我
遇见更好的自我 2021-01-24 18:51

I have implemented a subset of the forward_list and wanted to test the method assign(size_type __n, const _Tp& __val) but I get a compiler error be

2条回答
  •  傲寒
    傲寒 (楼主)
    2021-01-24 19:08

    When you call l.assign(10, 5);, there are two viable overloads:

    void assign(size_type n, const int& val)
    
    template <>
    void assign(int first, int last)
    

    When we say that non-template functions are preferred to template functions, that is only true if the two have indistinguishable conversion sequences. But in this case, the function template will match exactly (both of your arguments are int, no conversion necessary), while the non-template will have to undergo promotation (have to promote 10 from int to size_t). So that's why the function template overload is preferred.

    As to how to fix it, you just need to make the template not a viable overload. That involves writing a type_trait for input iterator, which using void_t is not hard:

    template 
    using void_t = void;
    
    template 
    struct is_input_iterator : std::false_type { };
    
    template 
    struct is_input_iterator() == std::declval()),
        decltype(std::declval() != std::declval()),
        decltype(*std::declval()),
        decltype(++std::declval()),
        decltype(std::declval()++)
        >> : std::true_type { };
    

    And then require is_input_iterator:

    template ::value>>
    void assign(_InputIterator first, _InputIterator last);
    

    There are lots of other ways to do this sort of thing, I just happen to like void_t. Regardless of which way you do it, you have to ensure that the template simply isn't viable.

提交回复
热议问题