std::declval 的作用
std::declval
的作用
std::declval
是 C++ 标准库中的一个工具,用于在不创建对象的情况下获得一个类型的引用。其主要作用是在编译时期在表达式中使用一个类型的实例而不实际构造对象。这在模板元编程和 SFINAE 中尤其有用,因为它允许我们在编译时对类型的潜在成员进行推断和检查。
std::declval
在 <utility>
头文件中定义,并且仅在 unevaluated context(未求值上下文,例如 sizeof 和 decltype 中)是合法的,这意味着它不能用于在运行时创建对象。
std::declval
的使用场景
1. 类型推导
最常见的场景是在使用 decltype
来推导表达式的类型时,尤其是当你需要推导一个类的成员函数的返回类型,但又不想或不能创建这个类的实例。
例如,下面的代码展示了如何使用 std::declval
来推导成员函数的返回类型:
1 |
|
在这里,decltype
用来确定 myFunction
的返回类型,而 std::declval<MyClass>()
“假装” 有一个 MyClass
的对象来允许我们调用成员函数。
2. SFINAE 和类型萃取
在 SFINAE(替换失败并非错误)或写类型萃取(trait)时,std::declval
能够确保在没有默认构造函数的情况下依然能进行操作。
1 |
|
在这个例子中,即使 MyClass
没有默认构造函数,我们也能用 std::declval
来进行编译时检查。
3. 重载决策
在某些复杂的重载决策场景中,你可能希望根据类型是否支持某个操作来选择不同的函数重载。std::declval
可以在不创建对象的情况下 “假设” 该对象的存在,以便进行这样的检查。
1 |
|
这里 std::declval
在编译时帮助确定 T
类型是否有一个名为 print
的成员函数。
小结
std::declval
是模板编程中一个极为有用的工具,它能够让程序员在不实例化对象的情况下引用任意类型,特别是在仅仅需要类型信息而不需要对象的场合。它通常与 decltype
结合使用,以便在编译时对表达式类型进行操作和推导。由于 std::declval
仅在未求值上下文中有效,因此它
主要用于模板元编程和编译时类型推导,而不是在实际运行时代码中创建对象。