C++17中的类模板参数推导

      在C++17之前,必须明确指出类模板的所有参数。自从C++17起必须指明类模板参数的限制被放宽了。通过使用类模板参数推导(Class Template Argument Deduction(CTAD)),只要编译器能根据初始值推导出所有模板参数,那么就可以不指明参数。

      C++17中的类模板参数推导:允许从构造函数参数推导模板参数,简而言之,编译器可以根据构造函数参数自动推导它们,而不是显式指定模板参数。

      用户定义的推导指南(User-defined deduction guides):允许你为类模板参数推导提供自定义规则。这些指南帮助编译器根据构造函数参数推断模板参数。

      别名模板的推导(deduction for alias templates):允许你根据别名模板的基础类型或值(underlying type or value)推导别名模板的模板参数。

      注意
      (1).推导过程中模板参数必须没有歧义
      (2).推导模板参数时不会使用隐式类型转换。
      (3).仅当不存在模板参数列表时才执行类模板参数推导。如果指定了模板参数列表,则不会发生推导。
      (4).类模板参数推导过程中会首先尝试以拷贝的方式初始化。
      (5).类模板不能只指明一部分模板参数,然后指望编译器去推导剩余的部分参数。
      (6).在任何情况下,对于像std::vector<>或其他STL容器一样拥有复杂的构造函数的类模板,强烈建议不要使用类模板参数推导,而是显式指明类型。
      (7).智能指针没有推导指引。

      以下为测试代码:

namespace {

template<typename T>
class Foo {
public:
	Foo(T value)
	{
		std::cout << "Created Foo, type id: " << typeid(T).name() << ", value: " << value << "\n";
	}
};

template<typename T>
class Foo2 {
public:
	Foo2(T value)
	{
		std::cout << "Created Foo2, type id: " << typeid(T).name() << ", value: " << value << "\n";
	}
};

// User-defined deduction guide 
template<typename T> Foo2(T)->Foo2<T>;

template<typename T> using MyAlias = T;

template<typename T>
class Foo3 {
public:
	Foo3(const std::initializer_list<T>& list) : vec_(list) {}
	void print() const
	{
		for (const auto& val : vec_) {
			std::cout << val << " ";
		}
		std::cout << "\n";
	}

private:
	std::vector<T> vec_;
};

} // namespace

int test_ctad()
{
	// 只要能根据初始值推导出所有模板参数就可以使用类模板参数推导
	// 推导过程支持所有方式的初始化(只要保证初始化是有效的)
	std::pair p(2, 4.5);     // deduces to std::pair<int, double> p(2, 4.5);
	std::tuple t(4, 3, 2.5); // same as auto t = std::make_tuple(4, 3, 2.5);
	std::complex c{ 5.1, 3.3 }; // std::complex<double>
	std::mutex mx;
	std::lock_guard lg{ mx }; // std::lock_guard<std::mutex>
	std::vector vec{ "hello", "world" }; // std::vector<const char*>

	std::vector v1{ 42 };
	std::vector v2{ v1 }; // v2也是一个std::vector<int>,这是花括号初始化总是把列表中的参数作为元素这一规则的一个例外
	// 然而,如果用多于一个元素的初值列来初始化的话,就会把传入的参数作为元素并推导出其类型作为模板参数
	std::vector vv{ v1, v2 }; // vv是一个vector<vector<int>>


	// 1.Class Template Argument Deduction(CTAD)
	// not specifying the type of the template
	auto foo11 = Foo(88); // Created Foo, type id: int, value: 88
	auto foo12 = Foo("Beijing"); // Created Foo, type id: char const * __ptr64, value: Beijing

	// specifying the type of the template
	Foo<int> foo21(88); // Created Foo, type id: int, value: 88
	Foo<const char*> foo22("Beijing"); // Created Foo, type id: char const * __ptr64, value: Beijing


	// 2.User-defined deduction guides
	// not specifying the type of the template
	auto foo31 = Foo2(88); // Created Foo2, type id: int, value: 88
	auto foo32 = Foo2("Beijing"); // Created Foo2, type id: char const * __ptr64, value: Beijing


	// 3.the deduction for alias templates
	MyAlias<int> alias1{ 88 };
	MyAlias<std::string> alias2{ "Beijing" };

	std::cout << "alias1: " << alias1 << "\n"; // alias1: 88
	std::cout << "alias2: " << alias2 << "\n"; // alias2: Beijing

	// reference: https://www.geeksforgeeks.org/class-template-argument-deduction-in-cpp-17/
	auto foo41 = Foo3({ 1, 2, 3, 4, 5 });
	foo41.print(); // 1 2 3 4 5

	return 0;
}

      执行结果如下图所示:

      GitHubhttps://github.com/fengbingchun/Messy_Test

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模板参数推导(template argument deduction)是C++11引入的一个新特性,它可以自动推导模板参数,避免手动指定模板参数。 在使用模板函数或模板类时,通常需要手动指定模板参数,例如: ``` template<typename T> void foo(T t); int main() { foo<int>(1); // 指定模板参数为int return 0; } ``` 在上面的代码,我们调用了模板函数`foo`,并手动指定了模板参数为int。这种方式比较繁琐,容易出错。 模板参数推导可以自动推导模板参数,避免手动指定模板参数。例如: ``` template<typename T> void foo(T t); int main() { foo(1); // 自动推导模板参数为int return 0; } ``` 在上面的代码,我们调用了模板函数`foo`,并没有手动指定模板参数,编译器会自动推导模板参数为int。 模板参数推导可以用于函数模板和类模板的实例化过程。它可以根据函数参数或对象成员的类型,自动推导出模板参数的类型。例如: ``` template<typename T, int N> class Array { public: T data[N]; }; int main() { Array arr{1, 2, 3}; // 自动推导模板参数为int和3 return 0; } ``` 在上面的代码,我们定义了一个类模板`Array`,它有两个模板参数,一个是类型参数T,一个是整型参数N。在实例化`Array`对象时,我们只传入了一个参数{1, 2, 3},编译器会自动推导模板参数为int和3。 需要注意的是,模板参数推导只能用于函数模板和类模板的实例化过程,不能用于模板定义。在模板定义,必须手动指定模板参数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值