C++17中auto作为非类型模板参数

本文详细解释了C++中非类型模板参数的概念,包括其支持的类型以及在C++17后使用auto的关键变化。文章还通过示例展示了如何在模板函数和结构中使用这些参数,以及它们在constexpr和编译期常量中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      非类型模板参数是具有固定类型的模板参数,用作作为模板参数传入的constexpr值的占位符。非类型模板参数可以是以下类型:
      (1).整型;
      (2).枚举类型;
      (3).std::nullptr_t;
      (4).指向对象的指针或引用;
      (5).指向函数的指针或引用;
      (6).指向成员函数的指针或引用;
      (7).浮点类型(C++20起);
      (8).literal class type(C++20起);
      非类型模板参数主要在我们需要将constexpr值传递给函数(或类类型)时使用,以便它们可以在需要常量表达式的上下文中使用。
      自从C++17起,我们可以使用auto作为非类型模板参数的类型。模板参数中的auto关键字可用于指示非类型参数,其类型是在实例化时推导的

      以下是测试代码:

namespace {

template<int num> // declare a non-type template parameter of type int named num
void print() { std::cout << "num: " << num << "\n"; }

// C++17之前
template <typename Type, Type value>
constexpr Type constant = value;
constexpr auto const int_constant_88 = constant<int, 88>;
constexpr auto const char_constant_y = constant<char, 'Y'>;

// C++17
template <auto value> // 不再需要明确地拼写类型
constexpr auto constant2 = value;
constexpr auto const int_constant2_88 = constant2<88>;
constexpr auto const char_constant2_y = constant2<'Y'>;

template<auto value>
void print_value() { std::cout << "value: " << value << "\n"; }

template<const auto* P> // 可以修饰auto, 例如,可以确保参数类型必须是个指针
struct S {};

// reference: https://github.com/MeouSker77/Cpp17/blob/master/markdown/src/ch13.md
// 定义一个既可能是字符也可能是字符串的模板参数
template<auto Sep = ' ', typename First, typename... Args>
void print(const First& first, const Args&... args)
{
	std::cout << first;
	auto outWithSep = [](const auto& arg) {
		std::cout << Sep << arg;
	};
	(..., outWithSep(args));
	std::cout << '\n';
}

// 定义编译期常量
template<auto v>
struct constant3
{
	static constexpr auto value = v;
};

using i = constant3<88>;
using c = constant3<'Y'>;
using b = constant3<true>;

// 使用auto作为变量模板的参数
template<typename T, auto N> std::array<T, N> arr;

void print_arr()
{
	std::cout << "arr<int, 5>:  ";
	for (const auto& elem : arr<int, 5>) {
		std::cout << elem << ' ';
	}

	std::cout << "\narr<int, 5u>: ";
	for (const auto& elem : arr<int, 5u>) {
		std::cout << elem << ' ';
	}
	std::cout << '\n';
}

} // namespace

int test_template_argument_auto()
{
	print<88>(); // num: 88


	std::cout << "constant: " << int_constant_88 << ", " << char_constant_y << "\n"; // constant: 88, Y
	std::cout << "constant2: " << int_constant2_88 << ", " << char_constant2_y << "\n"; // constant2: 88, Y

	print_value<88>(); // value: 88
	print_value<'Y'>(); // value: Y


	const std::string s{ "world" };
	print(7.5, "hello", s); // 7.5 hello world

	print<'-'>(7.5, "hello", s); // 7.5-hello-world
	print<-11>(7.5, "hello", s); // 7.5-11hello-11world

	static const char sep[] = ", ";
	print<sep>(7.5, "hello", s); // 7.5, hello, world

	std::cout << "i: " << i::value << ", c: " << c::value << ", b: " << b::value << "\n"; // i: 88, c: Y, b: 1


	arr<int, 5>[0] = 17;
	arr<int, 5>[3] = 42;
	arr<int, 5u>[1] = 11;
	arr<int, 5u>[3] = 33;
	print_arr(); // arr<int, 5>:  17 0 0 42 0
				 // arr<int, 5u>: 0 11 0 33 0

	return 0;
}

      执行结果如下图所示:

      GitHubhttps://github.com/fengbingchun/Messy_Test

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值