std::vector<T>
类有以下两个构造函数:
vector(size_type count, const T& value, const Allocator& alloc = Allocator());
template <class InputIt>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
当用 T=size_t
实例化时,这些似乎能够发生冲突(与 InputIt=size_t
),但它不会发生。为什么?
为了清楚起见,这里有一个最小的代码示例:
#include <iostream>
template <typename T>
struct A {
A(size_t n, const T &v) { std::cout << n << " x " << v << std::endl; }
template <typename I>
A(I first, I last) { std::cout << first << " ... " << last << std::endl; }
};
int main() {
size_t x = 3, y = 42;
A<size_t> a1(x, y); // prints 3 x 42
A<size_t> a2(3, 42); // prints 3 ... 42
}
编辑:我也将 @jrok 的版本放在示例中。为什么 a1
中的构造函数之一被优先考虑,另一个在 a2
中?
最佳答案
在重载解析期间,编译器需要在 InputIt
时从候选函数集中删除模板重载。不会被推导为迭代器类型(更正式地说,当它不满足 LegacyInputIterator
概念时 - 请参阅 this page 上的注释 (5))。
删除用户代码中的重载是通过 SFINAE 完成的技术,尽管编译器实现可以使用其他东西 - 它们并不严格要求使用合法的 C++ 代码。例如,我的(MinGW)编译器使用 SFINAE 实现它:
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type());
哪里_RequireInputIter
是
template<typename _InIter>
using _RequireInputIter = typename
enable_if<is_convertible<typename
iterator_traits<_InIter>::iterator_category,
input_iterator_tag>::value>::type;
此要求在 C++11 中生效,因此在此之前,您实际上可能会调用错误的构造函数。如果我们稍微修改一下您的示例:
#include <iostream>
template <typename T>
struct A {
A(size_t n, const T &v) { std::cout << n << " x " << v << std::endl; }
template <typename I>
A(I first, I last) { std::cout << first << " ... " << last << std::endl; }
};
int main() {
A<size_t> a(3, 42);
}
现在打印 3 ... 42
.
关于c++ - 编译器如何区分 std::vector 的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60339723/