Proper dispatch

This commit is contained in:
NaifBanana 2026-01-14 03:05:10 -06:00
parent 91ba24703a
commit c4ee778040

View File

@ -16,9 +16,57 @@ namespace nb {
template <typename StreamType, typename... Mixins> template <typename StreamType, typename... Mixins>
class SmartStream; class SmartStream;
template<typename C, typename T, typename... Mixins> template<typename StreamFormat, typename U, typename Mix>
class SmartStream<std::basic_ostream<C, T>, Mixins...> : public virtual Mixins... { struct MixinHasProcess {
using StreamType = std::basic_ostream<C, T>; protected:
template <typename M>
static auto test(int)->decltype(
M::process(std::declval<StreamFormat&>(), std::declval<const U&>()),
std::true_type{}
);
template <typename>
static std::false_type test(...);
public:
static const bool value = decltype(test<Mix>(0))::value;
};
template<typename StreamFormat, typename U, typename... Mixins>
struct PackHasProcess;
template<typename StreamFormat, typename U, typename Mix>
struct PackHasProcess<StreamFormat, U, Mix> {
static const bool value = MixinHasProcess<StreamFormat, U, Mix>::value;
using type = typename std::conditional<
value,
Mix,
void
>::type;
};
template<typename StreamFormat, typename U, typename Mix1, typename... Mixins>
struct PackHasProcess<StreamFormat, U, Mix1, Mixins...> {
protected:
static const bool base_value = MixinHasProcess<StreamFormat, U, Mix1>::value;
public:
static const bool value = std::conditional<
base_value,
std::true_type,
typename PackHasProcess<StreamFormat, U, Mixins...>::value
>::type::value;
using type = typename std::conditional<
base_value,
Mix1,
typename PackHasProcess<StreamFormat, U, Mixins...>::type
>::type;
};
template<typename ST, typename... Mixins>
class SmartStream<ST, Mixins...> : public virtual Mixins... {
using StreamType = typename std::conditional<
std::is_base_of<std>::value
>::type;
protected: protected:
StreamType* const _stream; StreamType* const _stream;
@ -30,13 +78,20 @@ public:
using Mixins::process...; using Mixins::process...;
template <typename U, typename StreamFmt=SmartStream<StreamType, Mixins...>> template <typename U, typename StreamFmt=SmartStream<StreamType, Mixins...>>
static void process(SmartStream& stream, const U& val, StreamFmt* fmtas=nullptr) { static typename std::enable_if<PackHasProcess<StreamFmt, U, Mixins...>::value, void>::type
toStream(SmartStream& stream, const U& val, const StreamFmt* fmtas=nullptr) {
PackHasProcess<StreamFmt, U, Mixins...>::type::process(stream, val);
}
template <typename U, typename StreamFmt=SmartStream<StreamType, Mixins...>>
static typename std::enable_if<!PackHasProcess<StreamFmt, U, Mixins...>::value, void>::type
toStream(SmartStream& stream, const U& val, const StreamFmt* fmtas=nullptr) {
*(stream._stream) << val; *(stream._stream) << val;
} }
template <typename ST, typename U, typename... Mixes> template <typename ST, typename U, typename... Mixes>
friend SmartStream<ST, Mixes...>& operator<<(SmartStream<ST, Mixes...>& stream, const U& val) { friend SmartStream<ST, Mixes...>& operator<<(SmartStream<ST, Mixes...>& stream, const U& val) {
SmartStream<ST, Mixes...>::process(stream, val); SmartStream<ST, Mixes...>::toStream(stream, val);
return stream; return stream;
} }
}; };