推断非类型模板参数的类型
Infer type of non-type template argument
我不擅长模板元编程,如果这是一个愚蠢的问题,我深表歉意。
我有这样的类型
template<int n>
struct S
{
typedef decltype(n) type_of_n;
// ...
};
我想编写类似于
的函数
template<
typename T,
typename T::type_of_n n,
typename = std::enable_if_t<std::is_same<T, S<n>>::value>>
void f(const T &) { /* ... */ }
的想法是,如果 S 的非类型模板参数的类型在将来的某个时候发生变化(比如 std::size_t
或 int64_t
或其他),那么调用代码将继续工作。但是我不确定如何让编译器在这里同时推断出 T
和 n
。
我唯一想到的基本上都是黑客:
- 在
S
之外做类似 typedef int type_of_S_n
的事情。
- 写类似
S<0>::type_of_n
的东西而不是实际推断类型
我想做的事情可行吗?如果没有,是否有比上面的 hack 更“干净”的方法?
if the type of the non-type template argument to S changes at some point in the future (say to std::size_t or int64_t or something) then calling code will just continue working.
您可以在 C++17 中使用 占位符类型 auto
,如下所示:
template<auto n> //note the auto here
struct S
{
typedef decltype(n) type_of_n;
// ...
};
你可以做一个特征来知道一个类型是否是 S<n>
:
template <typename T>
struct is_a_S : std::false_type {};
template <int N>
struct is_a_S<S<N>> : std::true_type {};
那你的SFINAE就可以这样搞了:
template<
typename T,
std::enable_if_t<is_a_S<T>::value, int> = 0>
void f(const T &) { /* ... */ }
C++20 概念让事情变得更简单
#include <concepts>
template<int n>
struct S {
typedef decltype(n) type_of_n;
};
template<class T>
requires std::same_as<T, S<typename T::type_of_n{}>>
void f(const T &) { /* ... */ }
如果您只想接受 S
并且还想推导 n
的值,那么您可以从 c++17 开始使用 auto
来推导 auto
的类型non-type 模板参数。
template<auto n>
void f(const S<n> &) { /* ... */ }
您还可以使其更通用,并通过使用模板模板参数接受具有单个 non-type 参数的任何类型。
template<template <auto> typename T, auto n>
void f(const T<n> &) { /* ... */ }
我不擅长模板元编程,如果这是一个愚蠢的问题,我深表歉意。
我有这样的类型
template<int n>
struct S
{
typedef decltype(n) type_of_n;
// ...
};
我想编写类似于
的函数template<
typename T,
typename T::type_of_n n,
typename = std::enable_if_t<std::is_same<T, S<n>>::value>>
void f(const T &) { /* ... */ }
的想法是,如果 S 的非类型模板参数的类型在将来的某个时候发生变化(比如 std::size_t
或 int64_t
或其他),那么调用代码将继续工作。但是我不确定如何让编译器在这里同时推断出 T
和 n
。
我唯一想到的基本上都是黑客:
- 在
S
之外做类似typedef int type_of_S_n
的事情。 - 写类似
S<0>::type_of_n
的东西而不是实际推断类型
我想做的事情可行吗?如果没有,是否有比上面的 hack 更“干净”的方法?
if the type of the non-type template argument to S changes at some point in the future (say to std::size_t or int64_t or something) then calling code will just continue working.
您可以在 C++17 中使用 占位符类型 auto
,如下所示:
template<auto n> //note the auto here
struct S
{
typedef decltype(n) type_of_n;
// ...
};
你可以做一个特征来知道一个类型是否是 S<n>
:
template <typename T>
struct is_a_S : std::false_type {};
template <int N>
struct is_a_S<S<N>> : std::true_type {};
那你的SFINAE就可以这样搞了:
template<
typename T,
std::enable_if_t<is_a_S<T>::value, int> = 0>
void f(const T &) { /* ... */ }
C++20 概念让事情变得更简单
#include <concepts>
template<int n>
struct S {
typedef decltype(n) type_of_n;
};
template<class T>
requires std::same_as<T, S<typename T::type_of_n{}>>
void f(const T &) { /* ... */ }
如果您只想接受 S
并且还想推导 n
的值,那么您可以从 c++17 开始使用 auto
来推导 auto
的类型non-type 模板参数。
template<auto n>
void f(const S<n> &) { /* ... */ }
您还可以使其更通用,并通过使用模板模板参数接受具有单个 non-type 参数的任何类型。
template<template <auto> typename T, auto n>
void f(const T<n> &) { /* ... */ }