在编写自定义类型特征时,我经常从标准库类型特征中获取它们,如下所示:
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
继承可能会改变应用程序行为的微妙场景?
答案 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
)。