Request Short Link
C++ 98
C++ 11
C++ 14
C++ 17
C++ 20
C++ 23
C++ 2c
for-loops as while-loops
array subscription
Show all implicit casts
Show all template parameters of a CallExpr
Use libc++
Transform std::initializer_list
Show noexcept internals
Show padding information
Show coroutine transformation
Show C++ to C transformation
Show object lifetime
Default
15
18
20
22
26
More
GitHub
Patreon
Issues
About
Policies
Examples
C++ Insights @ YouTube
Settings
Version
Bring C++ expertise to your team! Click for details
×
Made by
Andreas Fertig
Powered by
Flask
and
CodeMirror
Source:
#include <memory> #include <type_traits> #include <variant> #include <vector> #include <list> struct EnumPlaceholder { }; template <typename T> struct ChannelTypeIdentity { using Type = T; }; template <template <typename, typename> typename T> struct ContainerTypeIdentity; template <> struct ContainerTypeIdentity<std::vector> { template <typename U> using Type = std::vector<U>; }; template <> struct ContainerTypeIdentity<std::list> { template <typename U> using Type = std::list<U>; }; enum class ValueType { eUndefined, eBool, eUInt8T, eUInt16T, eUInt32T, eUInt64T, eInt8T, eInt16T, eInt32T, eInt64T, eFloat, eDouble, eEnum, eString }; enum class ContainerType { eNone, eVector, eList }; using ChannelTypeMapperReturnType = std::variant< ChannelTypeIdentity<EnumPlaceholder>, ChannelTypeIdentity<uint8_t>, ChannelTypeIdentity<uint16_t>, ChannelTypeIdentity<uint32_t>, ChannelTypeIdentity<uint64_t>, ChannelTypeIdentity<int8_t>, ChannelTypeIdentity<int16_t>, ChannelTypeIdentity<int32_t>, ChannelTypeIdentity<bool>, ChannelTypeIdentity<float>, ChannelTypeIdentity<double>, ChannelTypeIdentity<std::string> >; using ContainerTypeMapperReturnType = std::variant< ContainerTypeIdentity<std::vector>, ContainerTypeIdentity<std::list> >; ChannelTypeMapperReturnType simulateChannelTypeMapperReverseMap() { return ChannelTypeMapperReturnType(ChannelTypeIdentity<int32_t>()); } ContainerTypeMapperReturnType simulateContainerTypeMapperReverseMap() { return ContainerTypeMapperReturnType(ContainerTypeIdentity<std::vector>{}); } template <typename Func, typename ChannelTypeId> constexpr auto invoke(Func&& func, ChannelTypeId channelTypeId) { const auto valueType = simulateChannelTypeMapperReverseMap(); // simulated value, normally lookup in mapper if (channelTypeId.containerType != ContainerType::eNone) { return std::visit( [&channelTypeId, func = std::forward<Func>(func)](const auto& valueIdentity) mutable { using ValueType = typename std::decay_t<decltype(valueIdentity)>::Type; return std::visit( [func = std::forward<Func>(func)](const auto& containerIdentity) { using Type = typename std::decay_t<decltype(containerIdentity)>::template Type<ValueType>; return func(ChannelTypeIdentity<Type>{}); }, simulateContainerTypeMapperReverseMap()); // simulated value, normally lookup in mapper }, valueType); } return std::visit(std::forward<Func>(func), valueType); } struct ChannelTypeId { ValueType valueType; ContainerType containerType; friend auto operator<=>(const ChannelTypeId&, const ChannelTypeId&) = default; }; class IWidget { public: IWidget() = default; virtual void doSth() = 0; virtual ~IWidget() = default; }; template <typename T> class Widget : public IWidget { public: void doSth() override { } }; template <typename T> class Factory { public: static std::unique_ptr<IWidget> create() { return std::make_unique<Widget<T>>(); } }; struct Callable { template <typename T> auto operator()(const T& identity) const { using ValueType = typename T::Type; return Factory<ValueType>::create(); } }; std::unique_ptr<IWidget> doSth(ChannelTypeId id) { // This does not work - linker complains return invoke( []([[maybe_unused]] const auto& identity) -> std::unique_ptr<IWidget> { using ValueType = typename std::decay_t<decltype(identity)>::Type; return Factory<ValueType>::create(); }, id); // This works // return invoke(Callable(), id); } int main() { auto ptr = doSth(ChannelTypeId{ .valueType = ValueType::eUInt32T, .containerType = ContainerType::eVector }); ptr->doSth(); }
Insight:
Console: