C++模板参数自动推导(附带实例)
模板在 C++ 中无处不在,但是如果总是要指定模板参数是很烦人的。在某些情况下,编译器实际上可以从上下文推导出模板参数,这个特性在 C++17 中可用,称为类模板参数推导,它使编译器能够根据初始化列表的类型推导出缺少的模板参数。
在 C++17 之前,你必须在初始化变量时指定所有的模板参数,因为为了实例化类模板,所有的参数都必须是已知的,例如:
当然,使用函数模板(例如 std::make_pair())可以避免显式指定模板参数的问题,这得益于函数模板参数的推导,允许我们编写如下代码:
对于下面这个 foo 类模板,我们可以编写以下 make_foo() 函数模板来达到相同的效果:
C++17 中可以跳过指定模板参数,编译器在以下情况下可以推导出它们:
1) 当声明变量或变量模板并初始化它时:
2) 当使用 new 表达式创建对象时:
3) 当执行类似函数的强制转换表达式时:
在 C++17 之前,你必须在初始化变量时指定所有的模板参数,因为为了实例化类模板,所有的参数都必须是已知的,例如:
std::pair<int, char const*> p{ 42, "demo" }; std::vector<int> v{ 1, 2 }; foo<int> f{ 42 };
当然,使用函数模板(例如 std::make_pair())可以避免显式指定模板参数的问题,这得益于函数模板参数的推导,允许我们编写如下代码:
auto p = std::make_pair(42, "demo");
对于下面这个 foo 类模板,我们可以编写以下 make_foo() 函数模板来达到相同的效果:
template <typename T> constexpr foo<T> make_foo(T&& value) { return foo{ value }; } auto f = make_foo(42);在 C++17 中,对于前面列举的示例,我们没有必要那样做。我们可以像下面这样编写代码:
std::pair p{42, "demo"};
C++17 中可以跳过指定模板参数,编译器在以下情况下可以推导出它们:
1) 当声明变量或变量模板并初始化它时:
std::pair p{ 42, "demo" }; // deduces std::pair<int, char const*> std::vector v{ 1, 2 }; // deduces std::vector<int> std::less<> l; // deduces std::less<void>
2) 当使用 new 表达式创建对象时:
template <class T> struct foo { foo(T v) :data(v) {} private: T data; }; auto f = new foo(42);
3) 当执行类似函数的强制转换表达式时:
std::mutex mx; // deduces std::lock_guard<std::mutex> auto lock = std::lock_guard(mx); std::vector<int> v; // deduces std::back_insert_iterator<std::vector<int>> std::fill_n(std::back_inserter(v), 5, 42);