I'm playing around a bit with named/typed parameters using variadic templates, and have the following class:
class audio_source_t
{
public:
virtual ~audio_source_t()
{
}
template<typename T...>
void receive(const T&... args)
{
auto tuple = std::tie(args...);
receive_impl(std::get<boost::optional<sample_rate_t>>(tuple),
std::get<boost::optional<nb_channels_t>>(tuple));
}
private:
virtual void receive(audio_frame_t& destination,
const boost::optional<sample_rate_t>& sample_rate_hint = nullptr,
const boost::optional<nb_channels_t>& nb_channels_hint = nullptr) const;
};
Where the parameters types are defined as:
template<typename T>
class explicit_class
{
public:
explicit sample_rate_t(T value)
: value_(value)
{
}
explicit operator T()
{
return value_;
}
private:
T value_;
};
class sample_rate_t : public explicit_class<int>{};
class nb_channels_t : public explicit_class<int>{};
So far so good, now I can use the class as follows:
audio_source.receive(boost::optional<sample_rate_t>(48000),
boost::optional<nb_channels_t >(2));
audio_source.receive(boost::optional<nb_channels_t>(2),
boost::optional<sample_rate_t>(48000));
Parameter order doesn't matter and it is explicit, great.
However, it would be even better if optional parameters, were actually optional and I wouldn't need to mention boost::optional
for specified parameters, e.g.
audio_source.receive(sample_rate_t(48000),
nb_channels_t(2));
audio_source.receive(nb_channels_t(2),
sample_rate_t(48000));
audio_source.receive(sample_rate_t(48000));
audio_source.receive(nb_channels_t(2));
I know that I could just simply create all the possible overloads, however when I get up to +3 parameters, that quickly turn impractical.
Any suggestions as to how to achieve this improvement?
Basically what I need is something like:
get_or_nullptr_t<sample_rate_t>(tuple)
Which during compile time can decide whether the tuple contains the type and otherwise return std::nullptr_t()
.