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