diff --git a/engine/NBCore/SmartStreams.hpp b/engine/NBCore/SmartStreams.hpp index 17bde86..3fe0802 100644 --- a/engine/NBCore/SmartStreams.hpp +++ b/engine/NBCore/SmartStreams.hpp @@ -16,9 +16,57 @@ namespace nb { template class SmartStream; -template -class SmartStream, Mixins...> : public virtual Mixins... { - using StreamType = std::basic_ostream; +template +struct MixinHasProcess { +protected: + template + static auto test(int)->decltype( + M::process(std::declval(), 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 +class SmartStream : public virtual Mixins... { + using StreamType = typename std::conditional< + std::is_base_of::value + >::type; protected: StreamType* const _stream; @@ -30,13 +78,20 @@ public: using Mixins::process...; template > - static void process(SmartStream& stream, const U& val, StreamFmt* fmtas=nullptr) { + static typename std::enable_if::value, void>::type + toStream(SmartStream& stream, const U& val, const StreamFmt* fmtas=nullptr) { + PackHasProcess::type::process(stream, val); + } + + template > + static typename std::enable_if::value, void>::type + toStream(SmartStream& stream, const U& val, const StreamFmt* fmtas=nullptr) { *(stream._stream) << val; } template friend SmartStream& operator<<(SmartStream& stream, const U& val) { - SmartStream::process(stream, val); + SmartStream::toStream(stream, val); return stream; } };