Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从标准库类型特征继承_C++_C++11_Typetraits - Fatal编程技术网

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>}'