Сообщение Re[7]: Можно ли записать читабельнее? от 10.04.2023 16:25
Изменено 10.04.2023 16:30 rg45
Re[7]: Можно ли записать читабельнее?
R>Единственное отличие — не возникает ошибки компиляции в случае отсутствия обработчика. Вместо этого возвращается false, что означает, что запрос не был обработан. Таким образом, и пустые цепочки обработчиков тоже возможны. В остальном результат в точности как у тебя.
Хотя для того, чтобы вместо кода результата false получить ошибку компиляции, достаточно просто использовать констрейнт внутри функции overloaded. Следующий пример дает В ТОЧНОСТИ тот же эффект, что и твой:
http://coliru.stacked-crooked.com/a/c17469f02645ed84
Теперь если убрать def из списка обработчиков, то в соответствующих точках вызова, которые помечены комментариями "def", возникнут ошибки компиляции
Хотя для того, чтобы вместо кода результата false получить ошибку компиляции, достаточно просто использовать констрейнт внутри функции overloaded. Следующий пример дает В ТОЧНОСТИ тот же эффект, что и твой:
http://coliru.stacked-crooked.com/a/c17469f02645ed84
#include <cstdio>
#include <type_traits>
#include <utility>
#include <tuple>
template <typename T> concept available = std::is_same_v<T, T>;
template <typename F>
struct callable_wrapper
{
F f;
template <typename...X>
std::true_type operator()(X&&...x) const requires available<decltype(f(x...))> { f(x...); return {}; }
template <typename...X>
std::false_type operator()(X&&...) const { return {}; }
};
template <typename...F>
auto overloaded(F&&...f)
{
return [=](auto&&...x) requires std::disjunction_v<decltype(callable_wrapper<F>{f}(x...))...>
{
return (callable_wrapper<F>{f}(x...) || ...);
};
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Use case
void foo(int x) { printf("foo(%d)\n", x); }
void bar(const char* x) { printf("bar(\"%s\")\n", x); }
void buz(const void* x) { printf("buz(%p)\n", x); }
void def(...) { printf("def(...)\n"); }
int main()
{
const auto o = overloaded ( &foo, &bar, &buz, def );
printf("-----use:-----\n");
o(123); // foo
o("xxx"); // bar
o(&o); // baz
printf("-----misuse:-----\n");
o(123.45); // foo
o(nullptr); // bar
printf("-----default:-----\n");
o(&foo); // def
o(); // def
o(1, 2, 3); // def
}
Теперь если убрать def из списка обработчиков, то в соответствующих точках вызова, которые помечены комментариями "def", возникнут ошибки компиляции
Re[7]: Можно ли записать читабельнее?
R>Единственное отличие — не возникает ошибки компиляции в случае отсутствия обработчика. Вместо этого возвращается false, что означает, что запрос не был обработан. Таким образом, и пустые цепочки обработчиков тоже возможны. В остальном результат в точности как у тебя.
Хотя для того, чтобы вместо кода результата false получить ошибку компиляции, достаточно просто использовать констрейнт внутри функции overloaded. Следующий пример дает В ТОЧНОСТИ тот же эффект, что и твой:
http://coliru.stacked-crooked.com/a/c20f9298f6f339f5
Теперь если убрать def из списка обработчиков, то в соответствующих точках вызова, которые помечены комментариями "def", возникнут ошибки компиляции
Хотя для того, чтобы вместо кода результата false получить ошибку компиляции, достаточно просто использовать констрейнт внутри функции overloaded. Следующий пример дает В ТОЧНОСТИ тот же эффект, что и твой:
http://coliru.stacked-crooked.com/a/c20f9298f6f339f5
#include <cstdio>
#include <type_traits>
#include <utility>
#include <tuple>
template <typename T> concept available = std::is_same_v<T, T>;
template <typename F>
struct callable_wrapper
{
F f;
template <typename...X>
std::true_type operator()(X&&...x) const requires available<decltype(f(x...))> { f(x...); return {}; }
template <typename...X>
std::false_type operator()(X&&...) const { return {}; }
};
template <typename...F>
auto overloaded(F&&...f)
{
return [=](auto&&...x) requires std::disjunction_v<decltype(callable_wrapper<F>{f}(x...))...>
{
return (callable_wrapper<F>{f}(x...) || ...);
};
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Use case
void foo(int x) { printf("foo(%d)\n", x); }
void bar(const char* x) { printf("bar(\"%s\")\n", x); }
void buz(const void* x) { printf("buz(%p)\n", x); }
void def(...) { printf("def(...)\n"); }
int main()
{
const auto o = overloaded ( foo, bar, buz, def );
printf("-----use:-----\n");
o(123); // foo
o("xxx"); // bar
o(&o); // baz
printf("-----misuse:-----\n");
o(123.45); // foo
o(nullptr); // bar
printf("-----default:-----\n");
o(&foo); // def
o(); // def
o(1, 2, 3); // def
}
Теперь если убрать def из списка обработчиков, то в соответствующих точках вызова, которые помечены комментариями "def", возникнут ошибки компиляции