Сообщение Re[3]: Как узнать хранит ли variant... от 06.05.2025 8:30
Изменено 06.05.2025 11:24 rg45
Re[3]: Как узнать хранит ли variant...
Здравствуйте, Marty, Вы писали:
M>Ну, я хотел сделать фильтры, для преобразования выводимых строк после их форматирования, например, html/xml-escape, фильтры должны уметь передаваться как аргумент при вызове функции форматирования, наравне с самими форматируемыми величинами. А потом, внутри реализации, я решил присунуть стандартные фильтры, которые создаёт фабрика стандартных фильтров, которая задаётся параметром шаблона и возвращает такой же функтор, который может лежать в параметрах шаблона. Но конкретный тип функтора я не знаю, пользователь может не использовать мои алиасы. В аргументы стандартный фильтр я не могу запихивать, и я решил завести вектор фильтров, куда кладу либо созданный фабрикой стандартный фильтр, либо взятый из аргументов. А для этого мне надо знать тип функтора. Вот, как-то так. Пока даже что-то вырисовывается
Извини, что отвечаю с задержкой. Вот примерный эскиз. Использую концепты — просто потому что так компактнее и нагляднее, но переложить на SFINAE — это лишь дело техники.
https://coliru.stacked-crooked.com/a/29987ff10b6e141f
M>Ну, я хотел сделать фильтры, для преобразования выводимых строк после их форматирования, например, html/xml-escape, фильтры должны уметь передаваться как аргумент при вызове функции форматирования, наравне с самими форматируемыми величинами. А потом, внутри реализации, я решил присунуть стандартные фильтры, которые создаёт фабрика стандартных фильтров, которая задаётся параметром шаблона и возвращает такой же функтор, который может лежать в параметрах шаблона. Но конкретный тип функтора я не знаю, пользователь может не использовать мои алиасы. В аргументы стандартный фильтр я не могу запихивать, и я решил завести вектор фильтров, куда кладу либо созданный фабрикой стандартный фильтр, либо взятый из аргументов. А для этого мне надо знать тип функтора. Вот, как-то так. Пока даже что-то вырисовывается
Извини, что отвечаю с задержкой. Вот примерный эскиз. Использую концепты — просто потому что так компактнее и нагляднее, но переложить на SFINAE — это лишь дело техники.
https://coliru.stacked-crooked.com/a/29987ff10b6e141f
#include <iostream>
#include <functional>
#include <type_traits>
#include <variant>
/////////////////////////////////////////////////////////////////////////////////////////
// Вспомогательные инструменты
template <typename...T>
struct Inherited : std::decay_t<T>... {};
template <typename> struct IsFreeFunction : std::false_type{};
template<typename R, typename...A> struct IsFreeFunction<R(A...)> : std::true_type{};
template <typename T> struct IsFreeFunction<T*> : IsFreeFunction<T>{};
template <typename T>
concept FreeFunction = IsFreeFunction<std::decay_t<T>>::value;
template <typename T>
concept CallableObject =
std::is_class_v<std::decay_t<T>>
and not requires { &Inherited<T, decltype([]{})>::operator(); };
template <typename T>
concept Callable = FreeFunction<T> or CallableObject<T>;
template <typename T>
concept NotCallable = not Callable<T>;
template<CallableObject...T>
struct Overload : T... { using T::operator()...; };
template<CallableObject...T>
Overload(T&&...) -> Overload<std::decay_t<T>...>;
/////////////////////////////////////////////////////////////////////////////////////////
// Использование
template<typename InputIteratorType, typename OutputIteratorType>
using BasicFormatValueFilter = std::function <
OutputIteratorType(
InputIteratorType // begin
, InputIteratorType // end
, OutputIteratorType
)
>;
/////////////////////////////////////////////////////////////////////////////////////////
// Является ли текущее значение варианта экземпляром функтора
template <typename...T>
auto IsCallable(const std::variant<T...>& v) {
return std::visit(
Overload(
[](auto&&...) {return false;}
, [](Callable auto&&) {return true;}
)
, v
);
}
/////////////////////////////////////////////////////////////////////////////////////////
// Аналогично: есть ли что - либо на базе BasicFormatValueFilter
template <typename...T>
auto IsBasicFormatValueFilter(const std::variant<T...>& v) {
return std::visit(
Overload(
[](auto&&...) {return false;}
, []<typename I, typename O>(const BasicFormatValueFilter<I, O>&) {
// А вот получить точный тип содержимого ты можешь только здесь, внутри специальной функции
return true;
}
)
, v
);
}
int main()
{
using CustomInputIterator = const int*;
using CustomOutputIterator = double*;
using CustomFormatValueFilter = BasicFormatValueFilter<CustomInputIterator, CustomOutputIterator>;
using V = std::variant<int, double, CustomFormatValueFilter, std::function<double(double)>>;
std::cout << std::boolalpha;
std::cout << IsCallable(V{3.14}) << std::endl; // false
std::cout << IsCallable(V{[](double x){return x * 10;}}) << std::endl; // true
std::cout << "------------------------------------------------------------------------------" << std::endl;
auto customFilter = [](CustomInputIterator, CustomInputIterator, CustomOutputIterator) {
return CustomOutputIterator{};
};
std::cout << IsBasicFormatValueFilter(V{3.14}) << std::endl; // false
std::cout << IsBasicFormatValueFilter(V{3.14}) << std::endl; // false
std::cout << IsBasicFormatValueFilter(V{customFilter}) << std::endl; // true
}
Re[3]: Как узнать хранит ли variant...
Здравствуйте, Marty, Вы писали:
M>Ну, я хотел сделать фильтры, для преобразования выводимых строк после их форматирования, например, html/xml-escape, фильтры должны уметь передаваться как аргумент при вызове функции форматирования, наравне с самими форматируемыми величинами. А потом, внутри реализации, я решил присунуть стандартные фильтры, которые создаёт фабрика стандартных фильтров, которая задаётся параметром шаблона и возвращает такой же функтор, который может лежать в параметрах шаблона. Но конкретный тип функтора я не знаю, пользователь может не использовать мои алиасы. В аргументы стандартный фильтр я не могу запихивать, и я решил завести вектор фильтров, куда кладу либо созданный фабрикой стандартный фильтр, либо взятый из аргументов. А для этого мне надо знать тип функтора. Вот, как-то так. Пока даже что-то вырисовывается
Извини, что отвечаю с задержкой. Вот примерный эскиз. Использую концепты — просто потому что так компактнее и нагляднее. Но переложить на SFINAE — это лишь дело техники.
https://coliru.stacked-crooked.com/a/0a9e5a5ac7ee0af7
M>Ну, я хотел сделать фильтры, для преобразования выводимых строк после их форматирования, например, html/xml-escape, фильтры должны уметь передаваться как аргумент при вызове функции форматирования, наравне с самими форматируемыми величинами. А потом, внутри реализации, я решил присунуть стандартные фильтры, которые создаёт фабрика стандартных фильтров, которая задаётся параметром шаблона и возвращает такой же функтор, который может лежать в параметрах шаблона. Но конкретный тип функтора я не знаю, пользователь может не использовать мои алиасы. В аргументы стандартный фильтр я не могу запихивать, и я решил завести вектор фильтров, куда кладу либо созданный фабрикой стандартный фильтр, либо взятый из аргументов. А для этого мне надо знать тип функтора. Вот, как-то так. Пока даже что-то вырисовывается
Извини, что отвечаю с задержкой. Вот примерный эскиз. Использую концепты — просто потому что так компактнее и нагляднее. Но переложить на SFINAE — это лишь дело техники.
https://coliru.stacked-crooked.com/a/0a9e5a5ac7ee0af7
#include <iostream>
#include <functional>
#include <type_traits>
#include <variant>
/////////////////////////////////////////////////////////////////////////////////////////
// Вспомогательные инструменты
template <typename...T>
struct Inherited : std::decay_t<T>... {};
template <typename> struct IsFreeFunction : std::false_type{};
template<typename R, typename...A> struct IsFreeFunction<R(A...)> : std::true_type{};
template <typename T> struct IsFreeFunction<T*> : IsFreeFunction<T>{};
template <typename T>
concept FreeFunction = IsFreeFunction<std::decay_t<T>>::value;
template <typename T>
concept CallableObject =
std::is_class_v<std::decay_t<T>>
and not requires { &Inherited<T, decltype([]{})>::operator(); };
template <typename T>
concept Callable = FreeFunction<T> or CallableObject<T>;
template<CallableObject...T>
struct Overload : T... { using T::operator()...; };
template<CallableObject...T>
Overload(T&&...) -> Overload<std::decay_t<T>...>;
/////////////////////////////////////////////////////////////////////////////////////////
// Использование
template<typename InputIteratorType, typename OutputIteratorType>
using BasicFormatValueFilter = std::function <
OutputIteratorType(
InputIteratorType // begin
, InputIteratorType // end
, OutputIteratorType
)
>;
/////////////////////////////////////////////////////////////////////////////////////////
// Является ли текущее значение варианта экземпляром функтора
template <typename...T>
bool IsCallable(const std::variant<T...>& v) {
return std::visit(
Overload(
[](auto&&...) {return false;}
, [](Callable auto&&) {return true;}
)
, v
);
}
/////////////////////////////////////////////////////////////////////////////////////////
// Аналогично: есть ли что - либо на базе BasicFormatValueFilter
template <typename...T>
bool IsBasicFormatValueFilter(const std::variant<T...>& v) {
return std::visit(
Overload(
[](auto&&...) {return false;}
, []<typename I, typename O>(const BasicFormatValueFilter<I, O>&) {
// А вот получить точный тип содержимого ты можешь только здесь, внутри специальной функции
return true;
}
)
, v
);
}
int main()
{
using CustomInputIterator = const int*;
using CustomOutputIterator = double*;
using CustomFormatValueFilter = BasicFormatValueFilter<CustomInputIterator, CustomOutputIterator>;
using V = std::variant<int, double, CustomFormatValueFilter, std::function<double(double)>>;
std::cout << std::boolalpha;
std::cout << IsCallable(V{3.14}) << std::endl; // false
std::cout << IsCallable(V{[](double x){return x * 10;}}) << std::endl; // true
std::cout << "--" << std::endl;
auto customFilter = [](CustomInputIterator, CustomInputIterator, CustomOutputIterator) {
return CustomOutputIterator{};
};
std::cout << IsBasicFormatValueFilter(V{3.14}) << std::endl; // false
std::cout << IsBasicFormatValueFilter(V{3.14}) << std::endl; // false
std::cout << IsBasicFormatValueFilter(V{customFilter}) << std::endl; // true
}