Ответ 1
Вторая имеет второстепенную ловушку утечки деталей реализации; кто-то может проверить через перегрузку функции, если вы наследуете от is_arithmetic<int>
или что-то еще. Это может "работать" и приводить к ложным срабатываниям.
Это очень незначительная проблема.
Вы можете получить немного лучшую диагностику, наследуя от 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");
}
К сожалению, у нас нет эквивалента простого привязки/частичного приложения/каррирования в метапрограммировании шаблонов. Поэтому f<.> = is_base_of<X, .>
трудно выразить кратко.
Пример в реальном времени, мы получаем сообщения об ошибках: лязг:
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>}'
который по крайней мере приводит вас к ошибке (что const char*
не is_arithmetic
).