#pragma once #ifndef _NB_SMARTSTREAM #define _NB_SMARTSTREAM #include #include #include #include #include #include #include #include namespace nb { template class SmartStream; template struct MixinHasProcess { protected: template static auto test(int)->decltype( std::declval().template process(std::declval()), std::true_type{} ); template static std::false_type test(...); public: static const bool value = decltype(test(0))::value; }; template struct PackHasProcess; template struct PackHasProcess { static const bool value = MixinHasProcess::value; using type = typename std::conditional< value, Mix, void >::type; }; template struct PackHasProcess { protected: static const bool base_value = MixinHasProcess::value; public: static const bool value = std::conditional< base_value, std::true_type, typename PackHasProcess::value >::type::value; using type = typename std::conditional< base_value, Mix1, typename PackHasProcess::type >::type; }; /* template struct HasStreamType : std::false_type {}; template struct HasStreamType : std::false_type {}; */ template class SmartStream : public Mixins... { using StreamType = typename std::conditional< decltype(std::declval(), std::true_type{}), ST::StreamType, ST >::type; protected: StreamType* const _stream; public: SmartStream(StreamType& stream) : _stream(&stream), Mixins(&stream)... {} using Mixins::process...; template > typename std::enable_if::value, void>::type toStream(const U& val, const StreamFmt* fmtas=nullptr) { PackHasProcess::type::template process(val); } template > typename std::enable_if::value, void>::type toStream(const U& val, const StreamFmt* fmtas=nullptr) { *_stream << val; } template friend SmartStream& operator<<(SmartStream& stream, const U& val) { stream.toStream(val); return stream; } }; struct SmartText { int x; }; template struct ANSIFormatter { template void process(const SmartText& val, StreamType* fmtas = nullptr) { static_cast(this)->toStream(val.x); } protected: ANSIFormatter(StreamType* stream) : _stream(stream) {} StreamType* const _stream; }; } #endif // _NB_SMARTSTREAM