概念:在std
命名空间中声明的TransformationTrait
我在想,C++类型特征是否有一种方式可以限制它们的输入类型,使其不接受其他类型特征。
由于元函数特征本身就是类型(这也是问题的根源),我们可以利用这一点,并为T
构造一个概念,即在非评估上下文中,Argument-Dependent Lookup(ADL)能否找到一组更小的STL函数集,通过ADL在类型为T
的对象上查找(可能是脆弱的-见下文),其中T
可能潜在地是元函数特征。本质上,这是一种基于ADL的机制,用于查询给定类型T
是否定义在std
命名空间中,而不是冗长的查询是否T
恰好是在std
命名空间中定义的众多特征类型之一。
如果将此与TransformationTrait要求相结合:
C++命名要求:TransformationTrait
TransformationTrait是一个类模板,它提供了其模板类型参数的转换。
要求:
- 接受一个模板类型参数(其他模板参数是可选的且允许的)
- 转换后的类型是一个名为
type
的公共可访问嵌套类型。
我们可以构造一个通用概念,用于表示
T
类型在
std
命名空间中是否为TransformationTrait。但请注意,在这种意义上依赖ADL可能有些脆弱,如果某个项目出于某种原因开始声明从STL重载函数名称的函数,则会使情况变得更加复杂。扩展概念中用于可能的ADL查找的
较小选择集合的STL函数,将使非
std
实现人员难以摆脱。
例如,定义如下几个概念:
namespace traits_concepts {
template <typename T>
concept FindsStlFunctionByAdlLookupOnT = requires(T t) {
as_const(t);
move(t);
};
template <typename T>
concept IsTransformationTrait = requires {
typename T::type;
};
template <typename T>
concept IsStlTransformationTrait =
IsTransformationTrait<T> && FindsStlFunctionByAdlLookupOnT<T>;
template <typename T>
concept IsNotStlTransformationTrait = !IsStlTransformationTrait<T>;
}
应用于:
namespace not_std {
template <traits_concepts::IsNotStlTransformationTrait T>
struct NotAnStlTrait {
using type = T;
};
struct Foo {};
};
static_assert(
traits_concepts::IsStlTransformationTrait<std::remove_cv<const int>>);
static_assert(
!traits_concepts::IsStlTransformationTrait<std::remove_cv_t<const int>>);
static_assert(
!traits_concepts::IsStlTransformationTrait<not_std::NotAnStlTrait<int>>);
static_assert(!traits_concepts::IsStlTransformationTrait<not_std::Foo>);
int main() {}
如果我们是编译器供应商,并且将名称添加到std
命名空间,则对于自定义特征:
namespace std {
template <traits_concepts::IsNotStlTransformationTrait T>
struct custom_stl_trait {
using type = T;
};
};
static_assert(
traits_concepts::IsStlTransformationTrait<std::custom_stl_trait<int>>);
static_assert(!traits_concepts::IsStlTransformationTrait<
std::custom_stl_trait<int>::type>);
int main() {}
演示.