vuk*_*ung 2 c++ templates constructor vector
该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());
Run Code Online (Sandbox Code Playgroud)
当用 实例化时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
}
Run Code Online (Sandbox Code Playgroud)
编辑:我也在示例中放置了@jrok 的版本。为什么其中一个构造函数优先于a1,而另一个优先于a2?
在重载决议期间,编译器需要在InputIt未推导出为迭代器类型时从候选函数集中删除模板重载(更正式地说,当它不满足LegacyInputIterator概念时 - 请参阅本页上的注释 (5) )。
删除用户代码中的重载是使用SFINAE技术完成的,尽管编译器实现可以使用其他东西 - 它们并不严格要求使用合法的 C++ 代码。例如,我的 (MinGW) 编译器使用 SFINAE 实现它:
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type());
Run Code Online (Sandbox Code Playgroud)
这里_RequireInputIter是
template<typename _InIter>
using _RequireInputIter = typename
enable_if<is_convertible<typename
iterator_traits<_InIter>::iterator_category,
input_iterator_tag>::value>::type;
Run Code Online (Sandbox Code Playgroud)
此要求在 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);
}
Run Code Online (Sandbox Code Playgroud)
它现在打印3 ... 42.