C++17 详解 14

本文为 《C++17 in detail》 一书的中文渣中渣译文,不足之处还望指正。

4.4 用 auto 声明非类型模版参数

这是在任何地方使用 auto 策略的另一部分。C++11/14 里你可以利用 auto 自动推断变量甚至返回值的类型,另外还有泛型 lambda。现在你也可以利用它推断非类型模版参数了。

比如:

1
2
template <auto value> void f() { }
f<10>(); // 推断为 int

这很实用,因为你不必为指明非类型参数的类型而添加一个独立的参数了。

比如 C++11/14 里:

1
2
template <typename Type, Type value> constexpr Type TConstant = value;
constexpr auto const MySuperConst = TConstant<int, 100>;

C++17 里代码能稍稍简洁一点:

1
2
template <auto value> constexpr auto TConstant = value;
constexpr auto const MySuperConst = TConstant<100>;

不需要再显式地写明 Type 了。

异构编译时链表作为一种进阶用法在大量论文、文章中被引用:

1
2
template <auto ... vs> struct HeterogenousValueList {};
using MyList = HeterogenousValueList<'a', 100, 'b'>;

C++17 之前是不可能直接声明这样一个链表的,首先必须提供某种封装类。

扩展:本修改提案:P0127R2。在 P0127R1 里有更多示例和讨论。

4.5 其它修改

C++17 里还有其它一些跟模版相关的语言特性值得一提:

允许在模版的模版参数中使用 typename

译注:模版的模版参数(template template parameters),参数为模版的模版。

声明模版的模版参数时允许使用 typename 代替 class 关键字。普通类型参数可以互换使用两者,但是之前模版的模版参数被限制为只能使用 class。

更多信息参考 N4051

允许对所有非类型模版实参进行常量估算

移除对指针、引用、成员指针作为非类型模版参数时的语法限制。

更多信息参考 N4268

萃取中的变量模版

所有产出 ::value 的类型萃取都有一个伴随的 _v 变量模版。比如:

std::is_integral<T>::value 可以变成 std::is_integral_v<T>

std::is_class<T>::value 可以变成 std::is_class_v<T>

此改进源自 C++14 对返回 ::type 类型萃取添加的 _t 后缀(类型别名)。

更多信息参考 P0006R0

using 声明中的包展开

此特性是对可变参模版和参数包的加强。

现在编译器支持在包扩展中使用 using 关键字:

1
2
3
template<class... Ts> struct overloaded : Ts... {
using Ts::operator()...;
};

overloaded 类暴露所有来自基类的 operator() 重载版本。C++17 之前你必须递归使用参数包以实现相同结果。 overloaded 模式是对 std::visit 一个很有用的加强,在(后边)Variant 一章的 Overload 小节有更多讨论。

更多信息参考 P0195

逻辑操作元函数

C++17 添加了一些趁手的模版元函数:

  • template<class... B> struct conjunction; - 逻辑与
  • template<class... B> struct disjunction; - 逻辑或
  • template<class B> struct negation; - 逻辑非

这里是一份基于提案代码的示例:

1
2
3
4
5
6
template<typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<int, Ts>...> >
PrintIntegers(Ts ... args)
{
(std::cout << ... << args) << '\n';
}

PrintIntegers 函数同一组可变数量的参数一起工作,但是参数必须都是 int 类型。

这些辅助类元函数能提高复杂模版代码的可读性。

更多信息参考 P0013

4.6 编译器支持

略。

评论