Loading lang_cpp_tr_04...
<stdexcept>.
<fstream>, voir cette section)
double value=0.0; const bool available=bool(input_ >> value); // try to read from file if(available) { filter_.sample(value); // consider this new raw value value=filter_.mean(); // provide a filtered value }
std::tuple<bool, double>.
Sensor(const Sensor &rhs);
Sensor & operator=(const Sensor &rhs);✍
Sensor::operator=dans la définition.
auto copy{rhs}; return *this=std::move(copy);
Sensor(Sensor &&) =default;
Sensor & operator=(Sensor &&) =default;
~Sensor() =default;
//----------------------------------------------------------------------------
#ifndef ENCAP_ROLLING_MEAN_HPP #define ENCAP_ROLLING_MEAN_HPP
#include <vector> #include <iostream>
namespace encap {
class RollingMean { public:
RollingMean(std::vector<double> initial_samples);
RollingMean(int sample_count=5) : RollingMean{std::vector<double>(sample_count)} { }
int count() const { return int(size(samples_)); }
double mean() const;
void sample(double value);
private: std::vector<double> samples_; int next_; };
void fill(RollingMean &rm, double value);
std::ostream & operator<<(std::ostream &output, const RollingMean &rm);
} // namespace encap
#endif // ENCAP_ROLLING_MEAN_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "rolling_mean.hpp" #include <stdexcept>
namespace encap {
RollingMean::RollingMean(std::vector<double> initial_samples) : samples_{std::move(initial_samples)} , next_{0} { if(empty(samples_)) { throw std::runtime_error{"RollingMean must contain samples!"}; } }
double RollingMean::mean() const { double sum=0.0; for(const auto &elem: samples_) { sum+=elem; } return sum/count(); }
void RollingMean::sample(double value) { samples_[next_]=value; next_=(next_+1)%count(); }
void fill(RollingMean &rm, double value) { for(int i=0; i<rm.count(); ++i) { rm.sample(value); } }
std::ostream & operator<<(std::ostream &output, const RollingMean &rm) { return output << "{ " << rm.count() << " samples with mean " << rm.mean() << " }"; }
} // namespace encap
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#ifndef ENCAP_SENSOR_HPP #define ENCAP_SENSOR_HPP
#include "rolling_mean.hpp" #include <tuple> #include <fstream>
namespace encap {
class Sensor { public:
Sensor(std::string device);
#if 1
//-- provide copy -- Sensor(const Sensor &rhs); Sensor & operator=(const Sensor &rhs);
//-- default move is suitable -- Sensor(Sensor &&) =default; Sensor & operator=(Sensor &&) =default;
//-- default destruction is suitable -- ~Sensor() =default;
#endif
const std::string & device() const { return device_; }
std::tuple<bool, // available double> // value extract();
private: std::string device_; std::ifstream input_; RollingMean filter_; };
} // namespace encap
#endif // ENCAP_SENSOR_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "sensor.hpp"
namespace encap {
Sensor::Sensor(std::string device) : device_{std::move(device)} , input_{device_} , filter_{} { // nothing more to be done }
#if 1
Sensor::Sensor(const Sensor &rhs) : Sensor{rhs.device_} { // nothing more to be done }
Sensor & Sensor::operator=(const Sensor &rhs) { #if 1 // duplicate behavior of copy-construct device_=rhs.device_; input_=std::ifstream{device_}; filter_=RollingMean{}; return *this; #else // blindly reuse copy-construct and move-assign auto copy{rhs}; return *this=std::move(copy); #endif }
#endif
std::tuple<bool, // available double> // value Sensor::extract() { double value=0.0; const bool available=bool(input_ >> value); // try to read from file if(available) { filter_.sample(value); // consider this new raw value value=filter_.mean(); // provide a filtered value } return {std::move(available), std::move(value)}; }
} // namespace encap
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "rolling_mean.hpp" #include "sensor.hpp"
void test_RollingMean() { std::cout << "\n~~~~ " << __func__ << "() ~~~~\n"; #if 0 // encap::RollingMean rm{0}; #else encap::RollingMean rm; #endif for(int i=0; i<2*rm.count(); ++i) { const double value=0.2*(i+1); rm.sample(value); std::cout << value << " --> " << rm << '\n'; } fill(rm, 12.3); std::cout << "rm=" << rm << '\n'; }
void use_sensor(const std::string &title, encap::Sensor &s) {
std::cout << title << '\n'; std::cout << " device=" << s.device() << '\n'; std::cout << " values="; for(;;) { if(const auto [available, value]=s.extract(); available) { std::cout << ' ' << value; } else { break; } } std::cout << '\n'; }
void test_Sensor() { std::cout << "\n~~~~ " << __func__ << "() ~~~~\n"; encap::Sensor sensor{"device_A"}; #if 1 encap::Sensor tmp{sensor}; // copy-construct tmp from sensor sensor=tmp; // copy-assign back tmp to sensor #else encap::Sensor tmp{std::move(sensor)}; // move-construct tmp from sensor sensor=std::move(tmp); // move-assign back tmp to sensor #endif use_sensor("variable sensor", sensor); use_sensor("variable tmp", tmp); }
int main() { test_RollingMean(); test_Sensor(); return 0; }
//----------------------------------------------------------------------------