首页 > 编程笔记 > C++笔记 阅读:2

C++模板参数自动推导(附带实例)

模板在 C++ 中无处不在,但是如果总是要指定模板参数是很烦人的。在某些情况下,编译器实际上可以从上下文推导出模板参数,这个特性在 C++17 中可用,称为类模板参数推导,它使编译器能够根据初始化列表的类型推导出缺少的模板参数。

在 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);

相关文章