C++ 从标准库类型特征继承
在编写自定义类型特征时,我经常从标准库类型特征中派生它们,如下所示:C++ 从标准库类型特征继承,c++,c++11,typetraits,C++,C++11,Typetraits,在编写自定义类型特征时,我经常从标准库类型特征中派生它们,如下所示: template<typename T> struct some_type_trait: std::is_arithmetic<T> {}; 总的想法是,最终只有从std::bool_常量继承才有意义,但在第一个示例中,我们从std::bool_常量继承的事实是算术,而不是直接从std::bool_常量(如第二种情况)可通过多态性或实用程序(如std::is_base_of)观察到 要点是通过
template<typename T>
struct some_type_trait:
std::is_arithmetic<T>
{};
总的想法是,最终只有从std::bool_常量
继承才有意义,但在第一个示例中,我们从std::bool_常量
继承的事实是算术,而不是直接从std::bool_常量
(如第二种情况)可通过多态性或实用程序(如std::is_base_of
)观察到
要点是通过
type
成员类型直接从bool_常量
继承感觉更干净,因为这正是我们想要的。但是,从std::is_算术
继承稍微短一些,并且提供基本相同的行为。所以在选择一个或另一个(正确性、编译时…)时,是否有我可能遗漏的任何细微优势?与直接从底层的bool\u常量继承相比,从std::is\u算术继承可能会改变应用程序的行为,这是否存在一些微妙的情况?第二种情况存在泄漏实现细节的小陷阱;如果您继承自is_算术
或其他任何内容,则有人可以通过函数重载进行测试。这可能会“起作用”,并导致误报
这是一个极其次要的问题
如果编译器转储基类名称,则通过继承is_算术
可以获得稍微好一点的诊断
你的两个设计都不合拍。相反:
template<class T>
struct some_type_trait:
std::integral_constant<bool,
std::is_arithmetic<T>{}
>
{};
模板
构造某些类型的特征:
积分常数
{};
可以扩展,因为我们可以在其中放入任何表达式
正如我前面提到的,在错误消息中包含类型可能会有所帮助,因此我们可以:
constexpr bool all_of() { return true; }
template<class...Bools>
constexpr bool all_of(bool b0, Bools...bs) {
return b0 && all_of(bs...);
}
template<class T, template<class...>class...Requirements>
struct Requires : std::integral_constant<bool,
Requirements<T>{} &&...
// in C++11/14, something like: all_of(Requirements<T>::value...)
> {};
constexpr bool all_of(){return true;}
模板
constexpr bool all_of(bool b0,Bools…bs){
返回b0和所有(bs…);
}
模板
结构需要:std::integral_常量{};
然后我们得到:
template<class T>
using some_type_trait = Requires<T, std::is_arithmetic>;
模板
使用某种类型的特征=需要;
如果在标记分派中找不到重载,将生成一个错误,可能会给您提供线索
template<class T>
void test( std::true_type passes_test, T t ) {
std::cout << t+0 << "\n";
}
template<class T>
void test(T t) {
return test(some_type_trait<T>{}, t);
}
int main() {
test(3);
test("hello");
}
模板
无效测试(标准::真实类型通过测试,T){
std::cout这是一些高质量的bikeshedding:DFWIW,en.cppreference.com上的“可能实现”直接继承std::integral_常量
。遵循这种“风格”您的示例将继承自std::integral_constant
@DanielJour如果我没有弄错的话,继承自std::integral_constant
对于类型特征是必需的。问题是直接从std::integral_constant
派生还是通过类型特征间接派生它更好self.也许我不理解你的评论:/虽然我对直接从类型trait继承与使用它的type
成员类型相比是否有缺点/可能的陷阱太感兴趣了。我认为你需要从std::is_算术
继承才能选择延迟计算该特性。这就是我们如果你想要一个“干净的”接口您也可以使用some\u type\u trait\u t=some\u type\u trait::type
创建模板。编译器不会在该上下文中假设它是一个值,因为它不能是一个值。因此从继承is\u算术::type
很好。没有必要,但很好。@Barry为我没有编译而服务。删除了幽默的前缀。
template<class T>
void test( std::true_type passes_test, T t ) {
std::cout << t+0 << "\n";
}
template<class T>
void test(T t) {
return test(some_type_trait<T>{}, t);
}
int main() {
test(3);
test("hello");
}
main.cpp:23:10: note: candidate function [with T = const char *] not viable: no known conversion from 'some_type_trait<const char *>' (aka 'Requires<const char *, std::is_arithmetic>') to 'std::true_type' (aka 'integral_constant<bool, true>') for 1st argument
main.cpp:28:18: note: cannot convert 'Requires<const char*, std::is_arithmetic>()' (type 'Requires<const char*, std::is_arithmetic>') to type 'std::true_type {aka std::integral_constant<bool, true>}'