两个相同的构造函数,但编译器选择模板化的构造函数

问题描述 投票:0回答:2

我正在尝试用 C++ 实现一个列表容器,但编译器选择错误的重载时遇到问题。

重载如下:

list(size_type count, const T& value);
template<typename InputIt>
list(InputIt begin, InputIt end);

当我初始化源文件中的对象时,我无法阻止编译器选择第二个重载:

list<int> x(5, 45);

当给定的参数可迭代时,应该选择第二个重载,但我无法完成它。感谢您的帮助。

编辑:

类声明如下所示:

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);

    // ...
};
c++ c++17
2个回答
3
投票

当给定的参数是可迭代的但我无法完成它时,应该选择第二个重载?

您需要 SFINAE(“替换失败不是错误”) 构造函数之一(C++20 之前的版本),以便选择正确的构造函数。

// 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 */
{}

观看现场演示


但是,在 C++20 中,只需约束

std::input_or_output_iterator
:

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

观看现场演示


1
投票

问题在于,模板化 ctor 是“更好的匹配”,因为它对于传递的参数 545 都是“完全匹配”

,而非模板化 ctor 需要从 
int
size_type 的转换
 第一个参数 
5
有多种方法可以解决此问题,如其他答案所示。特别是,使用 c++20,您可以在模板化 ctor 上使用 
std::input_or_output_iterator

来约束它。

© www.soinside.com 2019 - 2024. All rights reserved.