Date: Sat, 16 Apr 2022 13:31:09 +0200
How I would see handling logic like this:
```
#include <tuple>
#include <stdexcept>
class ILaser
{
public:
virtual void trigger() = 0;
};
template<typename... Parts>
class LaserImpl : public ILaser
{
std::tuple<Parts...> _parts;
int _heat = 0;
public:
void trigger() final
{
float freq = 1;
float power = 1;
std::apply([&](auto... p){ ((void)p.update_freq(freq), ...);
}, _parts);
std::apply([&](auto... p){ ((void)p.update_power(power), ...);
}, _parts);
float charge = freq * power;
float heat = charge * 0.321f;
if (get_charge() > charge)
{
std::apply([&](auto... p){ ((void)p.use_charge(charge),
...); }, _parts);
std::apply([&](auto... p){ ((void)p.heat_sink(heat), ...);
}, _parts);
_heat += heat;
if (_heat > 1000)
{
throw std::runtime_error("Boom!");
}
}
}
float get_charge()
{
return std::apply([&](auto... p){ return (p.get_charge() +
...); }, _parts);
}
};
struct Nitrogen
{
float get_charge() { return 0; }
void update_freq(float& f) { }
void update_power(float& f) { f *= 10; }
void use_charge(float& f) { }
void heat_sink(float& f) { }
};
struct PicoSecond
{
float get_charge() { return 0; }
void update_freq(float& f) { f /= 100; }
void update_power(float& f) { }
void use_charge(float& f) { }
void heat_sink(float& f) { }
};
struct Battery
{
float charge = 300;
float get_charge() { return charge; }
void update_freq(float& f) { }
void update_power(float& f) { }
void use_charge(float& f) { auto m = std::min(f, charge); if (m >
0){ f -= m; charge -= m;} }
void heat_sink(float& f) { }
};
struct Heatsink
{
float get_charge() { return 0; }
void update_freq(float& f) { }
void update_power(float& f) { }
void use_charge(float& f) { }
void heat_sink(float& f) { f -= 30; }
};
class Laser : public LaserImpl<Nitrogen, PicoSecond, Battery,
Heatsink, Heatsink>
{
};
int main() {
Laser l;
l.trigger();
return l.get_charge();
}
```
https://godbolt.org/z/Tz3KnE4oq
sob., 16 kwi 2022 o 10:07 Frederick Virchanza Gotham via Std-Proposals
<std-proposals_at_[hidden]> napisaĆ(a):
>
> On 4/16/22, Thiago Macieira via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
>
> > How about this use-case:
> >
> > bool Klass::func(int &r)
> > {
> > if (this->Base1::func(r))
> > return true;
> > if (this->Base2::func2(r))
> > return true;
> > r = 3;
> > return false;
> > }
>
>
> I'm considering presenting an array of function pointers to
> programmers so that they have that kind of control. Here's an
> approximation of how my 'precompiler' would do it:
>
> #include <array>
>
> class Laser {
> public:
> virtual bool Trigger(void)
> {
> return true;
> }
> };
>
> class Laser_Nitrogen : virtual public Laser {
> public:
> bool Trigger(void) override
> {
> static std::array<bool (Laser::*)(void), 1u> const methods {
> &Laser::Trigger };
>
> for ( auto const &method : methods )
> {
> (this->*method)();
> }
>
> return false;
> }
> };
>
> class Laser_PicoSecond : virtual public Laser {
> public:
> bool Trigger(void) override
> {
> static std::array<bool (Laser::*)(void), 1u> const methods {
> &Laser::Trigger };
>
> return true;
> }
> };
>
> class Laser_NitrogenPicoSecond : public Laser_Nitrogen, public
> Laser_PicoSecond {
> public:
> bool Trigger(void) override
> {
> static std::array<bool (Laser::*)(void), 3u> const methods {
> &Laser::Trigger,
> static_cast<bool (Laser::*)(void)>(&Laser_Nitrogen::Trigger),
> static_cast<bool (Laser::*)(void)>(&Laser_PicoSecond::Trigger)
> };
>
> for ( auto const &method : methods )
> {
> if ( (this->*method)() ) return true;
> }
>
> return false;
> }
> };
>
>
> This sample experimental code has two problems:
>
> (1) It invokes the base method twice on the same object
> (2) It doesn't compile because of casting to a virtual base
>
> but I think you see the idea of what I'm trying to do.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
```
#include <tuple>
#include <stdexcept>
class ILaser
{
public:
virtual void trigger() = 0;
};
template<typename... Parts>
class LaserImpl : public ILaser
{
std::tuple<Parts...> _parts;
int _heat = 0;
public:
void trigger() final
{
float freq = 1;
float power = 1;
std::apply([&](auto... p){ ((void)p.update_freq(freq), ...);
}, _parts);
std::apply([&](auto... p){ ((void)p.update_power(power), ...);
}, _parts);
float charge = freq * power;
float heat = charge * 0.321f;
if (get_charge() > charge)
{
std::apply([&](auto... p){ ((void)p.use_charge(charge),
...); }, _parts);
std::apply([&](auto... p){ ((void)p.heat_sink(heat), ...);
}, _parts);
_heat += heat;
if (_heat > 1000)
{
throw std::runtime_error("Boom!");
}
}
}
float get_charge()
{
return std::apply([&](auto... p){ return (p.get_charge() +
...); }, _parts);
}
};
struct Nitrogen
{
float get_charge() { return 0; }
void update_freq(float& f) { }
void update_power(float& f) { f *= 10; }
void use_charge(float& f) { }
void heat_sink(float& f) { }
};
struct PicoSecond
{
float get_charge() { return 0; }
void update_freq(float& f) { f /= 100; }
void update_power(float& f) { }
void use_charge(float& f) { }
void heat_sink(float& f) { }
};
struct Battery
{
float charge = 300;
float get_charge() { return charge; }
void update_freq(float& f) { }
void update_power(float& f) { }
void use_charge(float& f) { auto m = std::min(f, charge); if (m >
0){ f -= m; charge -= m;} }
void heat_sink(float& f) { }
};
struct Heatsink
{
float get_charge() { return 0; }
void update_freq(float& f) { }
void update_power(float& f) { }
void use_charge(float& f) { }
void heat_sink(float& f) { f -= 30; }
};
class Laser : public LaserImpl<Nitrogen, PicoSecond, Battery,
Heatsink, Heatsink>
{
};
int main() {
Laser l;
l.trigger();
return l.get_charge();
}
```
https://godbolt.org/z/Tz3KnE4oq
sob., 16 kwi 2022 o 10:07 Frederick Virchanza Gotham via Std-Proposals
<std-proposals_at_[hidden]> napisaĆ(a):
>
> On 4/16/22, Thiago Macieira via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
>
> > How about this use-case:
> >
> > bool Klass::func(int &r)
> > {
> > if (this->Base1::func(r))
> > return true;
> > if (this->Base2::func2(r))
> > return true;
> > r = 3;
> > return false;
> > }
>
>
> I'm considering presenting an array of function pointers to
> programmers so that they have that kind of control. Here's an
> approximation of how my 'precompiler' would do it:
>
> #include <array>
>
> class Laser {
> public:
> virtual bool Trigger(void)
> {
> return true;
> }
> };
>
> class Laser_Nitrogen : virtual public Laser {
> public:
> bool Trigger(void) override
> {
> static std::array<bool (Laser::*)(void), 1u> const methods {
> &Laser::Trigger };
>
> for ( auto const &method : methods )
> {
> (this->*method)();
> }
>
> return false;
> }
> };
>
> class Laser_PicoSecond : virtual public Laser {
> public:
> bool Trigger(void) override
> {
> static std::array<bool (Laser::*)(void), 1u> const methods {
> &Laser::Trigger };
>
> return true;
> }
> };
>
> class Laser_NitrogenPicoSecond : public Laser_Nitrogen, public
> Laser_PicoSecond {
> public:
> bool Trigger(void) override
> {
> static std::array<bool (Laser::*)(void), 3u> const methods {
> &Laser::Trigger,
> static_cast<bool (Laser::*)(void)>(&Laser_Nitrogen::Trigger),
> static_cast<bool (Laser::*)(void)>(&Laser_PicoSecond::Trigger)
> };
>
> for ( auto const &method : methods )
> {
> if ( (this->*method)() ) return true;
> }
>
> return false;
> }
> };
>
>
> This sample experimental code has two problems:
>
> (1) It invokes the base method twice on the same object
> (2) It doesn't compile because of casting to a virtual base
>
> but I think you see the idea of what I'm trying to do.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2022-04-16 11:31:20