【问题标题】:class template constructor overload resolution ambiguity类模板构造函数重载解析歧义
【发布时间】:2019-10-31 15:20:32
【问题描述】:

我正在写一个类似stl vector的类模板,两个构造函数是这样的:

template<class T>
vector<T>::vector(size_t count, const T&value) :bg(new T[count]),
ed(bg + count), cap(ed) {
    for (auto it = bg; it != ed; ++it)
        *it = value;
}//bg ed cap are all T*

template<class T>
template<class Input>
vector<T>::vector(Input first, Input second) : bg(new T[second - first]),
ed(bg + (second - first)), cap(ed) {
    memcpy(bg, (void*)first, sizeof(T)*(second - first));
}

如果我这样做

vector<int>v(2,0)

编译器给我错误,似乎程序使用第二个构造函数而不是第一个。 谁能解释为什么? stl 向量说

这个重载只参与重载决议,如果 InputIt 满足 LegacyInputIterator,以避免与重载产生歧义 (3)。

那么我怎样才能改变我的代码来避免这种情况呢?提前致谢。

【问题讨论】:

标签: c++ class-template


【解决方案1】:

选择第二个重载是因为当Inputint 时它更好地匹配参数类型。具体来说,给定参数(int, int),重载(int, int) 比重载(size_t, int const&amp;) 更匹配。请注意,如果将第一个重载的第一个参数从size_t 更改为int,则会改为选择它。

如果您想在Input 是输入迭代器时禁用函数模板重载,您可以使用std::enable_if 来利用SFINAE

template <
    typename InputIt,
    typename = std::enable_if_t<
        std::is_base_of_v<
            std::input_iterator_tag,
            typename std::iterator_traits<InputIt>::iterator_category>>>
vector(InputIt, InputIt)
{
}

您可以选择将逻辑提取到类型特征中。

template <typename T, typename = void>
struct is_input_iterator : std::false_type
{
};

template <typename T>
struct is_input_iterator<T, std::void_t<typename std::iterator_traits<T>::iterator_category>>
: std::is_base_of<
    std::input_iterator_tag,
    typename std::iterator_traits<T>::iterator_category>
{
};

template <typename T>
constexpr bool is_input_iterator_v = is_input_iterator<T>::value;

然后函数定义变得更具可读性。

template <
    typename InputIt,
    typename = std::enable_if_t<is_input_iterator_v<InputIt>>>
vector(InputIt, InputIt)
{
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多