简单的概念检查
Simple concept check
假设我有一个像这样的简单模板:
template<typename T>
class A {};
我想指定类型参数 T
是一些不相关的类型 X<U>
,其中 U
未知(或无法指定)。
有没有办法将其表达为一个概念?
Is there a way how to express that as a concept?
您不需要概念,class 模板专业化在您的情况下工作得很好。
例如,您可以这样做:
template<typename T>
class A;
template<typename U>
class A<X<U>> { /* ... */ };
这样,除非 A
被实例化为 X<U>
形式的类型(其中 U
未知),否则你会得到一个编译时错误,因为主要未定义模板。换句话说,它不适用于所有类型,但 X<U>
(对于每个 U
),其中后者匹配具有正确定义的 class 模板特化。
请注意,我假设 X
是已知类型。从你的问题中不清楚。
无论如何,如果不是,并且您想为每个 X
和每个 U
接受形式为 X<U>
的类型,您仍然可以这样做:
template<typename T>
class A;
template<template<typename> class X, typename U>
class A<X<U>> { /* ... */ };
作为一个最小的工作示例:
template<typename>
struct S {};
template<typename>
class A;
template<typename U>
class A<S<U>> {};
int main() {
A<S<int>> aSInt;
A<S<double>> aSDouble;
// A<char> aChar;
}
A<S<int>>
和 A<S<double>>
都很好,示例可以编译。如果您切换注释,它将不再编译,因为 A<char>
根本没有定义。
附带说明一下,如果您不想使用 class 模板专业化并且想要模拟概念(请记住它们还不是标准的一部分,而且至少不会到 2020 年),你可以这样做:
#include<type_traits>
template<typename>
struct X {};
template<typename>
struct is_xu: std::false_type {};
template<typename U>
struct is_xu<X<U>>: std::true_type {};
template<typename T>
struct A {
static_assert(is_xu<T>::value, "!");
// ...
};
int main() {
A<X<int>> aXInt;
A<X<double>> aXDouble;
// A<char> aChar;
}
也就是说,给定一个泛型类型 T
,static 通过另一个结构(示例中的 is_xu
)验证其实际类型是否为 T
的形式X<U>
(每个U
)或不。
我的两分钱:class 模板专业化一目了然更易于阅读和理解。
template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };
现在给出一个 class 模板:
template <typename T>
struct X {};
可以使用以下方法约束类型模板参数:
template <typename T> requires Template<T, X>
class A {};
或:
template <Template<X> T>
class A {};
这也适用于派生自 X<U>
的类型。
假设我有一个像这样的简单模板:
template<typename T>
class A {};
我想指定类型参数 T
是一些不相关的类型 X<U>
,其中 U
未知(或无法指定)。
有没有办法将其表达为一个概念?
Is there a way how to express that as a concept?
您不需要概念,class 模板专业化在您的情况下工作得很好。
例如,您可以这样做:
template<typename T>
class A;
template<typename U>
class A<X<U>> { /* ... */ };
这样,除非 A
被实例化为 X<U>
形式的类型(其中 U
未知),否则你会得到一个编译时错误,因为主要未定义模板。换句话说,它不适用于所有类型,但 X<U>
(对于每个 U
),其中后者匹配具有正确定义的 class 模板特化。
请注意,我假设 X
是已知类型。从你的问题中不清楚。
无论如何,如果不是,并且您想为每个 X
和每个 U
接受形式为 X<U>
的类型,您仍然可以这样做:
template<typename T>
class A;
template<template<typename> class X, typename U>
class A<X<U>> { /* ... */ };
作为一个最小的工作示例:
template<typename>
struct S {};
template<typename>
class A;
template<typename U>
class A<S<U>> {};
int main() {
A<S<int>> aSInt;
A<S<double>> aSDouble;
// A<char> aChar;
}
A<S<int>>
和 A<S<double>>
都很好,示例可以编译。如果您切换注释,它将不再编译,因为 A<char>
根本没有定义。
附带说明一下,如果您不想使用 class 模板专业化并且想要模拟概念(请记住它们还不是标准的一部分,而且至少不会到 2020 年),你可以这样做:
#include<type_traits>
template<typename>
struct X {};
template<typename>
struct is_xu: std::false_type {};
template<typename U>
struct is_xu<X<U>>: std::true_type {};
template<typename T>
struct A {
static_assert(is_xu<T>::value, "!");
// ...
};
int main() {
A<X<int>> aXInt;
A<X<double>> aXDouble;
// A<char> aChar;
}
也就是说,给定一个泛型类型 T
,static 通过另一个结构(示例中的 is_xu
)验证其实际类型是否为 T
的形式X<U>
(每个U
)或不。
我的两分钱:class 模板专业化一目了然更易于阅读和理解。
template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };
现在给出一个 class 模板:
template <typename T>
struct X {};
可以使用以下方法约束类型模板参数:
template <typename T> requires Template<T, X>
class A {};
或:
template <Template<X> T>
class A {};
这也适用于派生自 X<U>
的类型。