class 模板构造函数重载解析歧义
class template constructor overload resolution ambiguity
我正在写一个class模板,像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)
complier 给我错误,程序似乎使用了第二个构造函数而不是第一个。
谁能解释为什么? stl 向量表示
This overload only participates in overload resolution if InputIt
satisfies LegacyInputIterator, to avoid ambiguity with the overload
(3).
那么我该如何更改我的代码来避免这种情况呢?提前致谢。
选择第二个重载是因为当 Input
为 int
时它能更好地匹配参数类型。具体来说,给定参数 (int, int)
,重载 (int, int)
比重载 (size_t, int const&)
更匹配。请注意,如果您将第一个重载的第一个参数从 size_t
更改为 int
,它将被选中。
如果你想在 Input
是一个输入迭代器时禁用函数模板重载,你可以利用 SFINAE using std::enable_if
:
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)
{
}
我正在写一个class模板,像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)
complier 给我错误,程序似乎使用了第二个构造函数而不是第一个。 谁能解释为什么? stl 向量表示
This overload only participates in overload resolution if InputIt satisfies LegacyInputIterator, to avoid ambiguity with the overload (3).
那么我该如何更改我的代码来避免这种情况呢?提前致谢。
选择第二个重载是因为当 Input
为 int
时它能更好地匹配参数类型。具体来说,给定参数 (int, int)
,重载 (int, int)
比重载 (size_t, int const&)
更匹配。请注意,如果您将第一个重载的第一个参数从 size_t
更改为 int
,它将被选中。
如果你想在 Input
是一个输入迭代器时禁用函数模板重载,你可以利用 SFINAE using std::enable_if
:
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)
{
}