继承标准库类型特征

时间:2017-04-19 10:12:50

标签: c++ c++11 typetraits

在编写自定义类型特征时,我经常从标准库类型特征中获取它们,如下所示:

template<typename T>
struct some_type_trait:
    std::is_arithmetic<T>
{};

但是,我有时想知道继承标准库类型特征的type成员类型是否更清晰:

template<typename T>
struct some_type_trait:
    std::is_arithmetic<T>::type
{};

总的想法是,只有std::bool_constant的继承最终才有意义,但事实是我们在第一个例子中继承std::is_arithmetic而不是直接来自std::bool_constant (如第二种情况)可以通过多态或类似std::is_base_of之类的实用程序观察到。

要点是直接从bool_constant通过type成员类型继承感觉更干净,因为它完全我们想要的东西。但是,从std::is_arithmetic继承的时间略短,并且提供的行为基本相同。所以......在选择其中一个时,我可能会遗漏任何微妙的优势(正确性,编译时......)?与直接从基础std::is_arithmetic继承相比,是否存在从bool_constant继承可能会改变应用程序行为的微妙场景?

1 个答案:

答案 0 :(得分:1)

第二个是泄漏实施细节的微小陷阱;如果你继承is_arithmetic<int>或其他什么,有人可以通过函数重载进行测试。这可能&#34;工作&#34;并导致误报。

这是一个非常小的问题。

如果编译器转储基类名称,则可以通过继承is_arithmetic来获得更好的诊断。

你的设计都不是很好。代替:

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...)
> {};

然后我们得到:

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");
}

遗憾的是,我们在模板元编程中没有相当于简单的绑定/部分应用/ currying。所以f<.> = is_base_of<X, .>很难简洁地表达出来。

Live example,我们收到的错误消息是: 铛:

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

GCC

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

至少会引发错误(const char*不是is_arithmetic)。