Mor*_*enn 15 c++ type-traits c++11
在编写自定义类型特征时,我经常从标准库类型特征派生它们,如下所示:
template<typename T>
struct some_type_trait:
std::is_arithmetic<T>
{};
Run Code Online (Sandbox Code Playgroud)
但是,我有时想知道继承type标准库类型特征的成员类型是否更清晰:
template<typename T>
struct some_type_trait:
std::is_arithmetic<T>::type
{};
Run Code Online (Sandbox Code Playgroud)
总的想法是只有std::bool_constant最终事物的继承,但我们从std::is_arithmetic第一个例子继承而不是直接从std::bool_constant(如第二种情况)继承的事实可以通过多态或类似的实现来观察std::is_base_of.
要点是直接从bool_constantvia type成员类型继承感觉更干净,因为它正是我们想要的.但是,继承的std::is_arithmetic时间稍短,并提供基本相同的行为.那么......在挑选其中一个时,我可能会遗漏任何微妙的优势(正确性,编译时......)?std::is_arithmetic与直接从底层继承相比,是否存在继承可能会改变应用程序行为的微妙场景bool_constant?
第二个有一个小缺陷,即泄露实现细节;如果您继承is_arithmetic<int>或其他什么,有人可以通过函数重载进行测试。这可能会“起作用”并导致误报。
这是一个非常小的问题。
is_arithmetic如果编译器转储基类名称,则通过继承可能会获得更好的诊断结果。
你们的设计都不好。反而:
template<class T>
struct some_type_trait:
std::integral_constant<bool,
std::is_arithmetic<T>{}
>
{};
Run Code Online (Sandbox Code Playgroud)
可以扩展,因为我们可以在其中放置任何表达式。
正如我之前指出的,在错误消息中包含类型会很有帮助,因此我们可以这样做:
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...)
> {};
Run Code Online (Sandbox Code Playgroud)
然后我们得到:
template<class T>
using some_type_trait = Requires<T, std::is_arithmetic>;
Run Code Online (Sandbox Code Playgroud)
如果它无法在标签调度中找到重载,则会生成一个错误,这可能会给您提供线索。
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");
}
Run Code Online (Sandbox Code Playgroud)
遗憾的是,我们在模板元编程中没有相当于简单绑定/部分应用/柯里化的功能。所以f<.> = is_base_of<X, .>很难简洁地表达。
活生生的例子,我们得到的错误消息是:clang:
Run Code Online (Sandbox Code Playgroud)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
海湾合作委员会:
Run Code Online (Sandbox Code Playgroud)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)。
| 归档时间: |
|
| 查看次数: |
410 次 |
| 最近记录: |