2016-09-25 1 views
0

J'ai le code suivant qui fonctionne très bien en renvoyant divers std::tuples aux divers mixins de ma classe hôte "BaseSensor".comment déballer un ensemble de tuples passés dans une classe Host de mixins (qui sont finalement transmis aux mixins)

#include <iostream> // std::cout std::endl 
#include <string> // std::string 
#include <map> // std::map 
#include <tuple> // std::map 

using namespace std; 

struct BaseSensorData 
{ 
    BaseSensorData(const string & _sensorName) 
     : sensorName(_sensorName) 
    {} 

    const string sensorName; 
}; 

class TrendSensor //mixin for BaseSensor 
{ 
    public: 
     TrendSensor(BaseSensorData * bsd , std::tuple<size_t , double > && tp) 
     { 
      cout << "TrendSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " " << std::get<1>(tp) << endl; 
     } 
}; 

typedef struct{ double trough; double peak; } Edges; 
class EdgeSensor //mixin for BaseSensor 
{ 
    public: 
     EdgeSensor(BaseSensorData * bsd , std::tuple<size_t , double > && tp) 
     { 
      cout << "EdgeSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " " << std::get<1>(tp) << endl; 
     } 
}; 

class CO2Threshold// : public ThresholdData 
{ 
    std::map<std::string , double>thresholds; 

    public: 
     CO2Threshold(const double & _toxicThres , const double & _zeroThres , const double &) 
     { 
      thresholds["toxic"] = _toxicThres; 
      thresholds["zero"] = _zeroThres; 
      cout << "CO2Threshold: " << _toxicThres << " " << thresholds["zero"] << endl; 
     } 
}; 
class O2Threshold// : public ThresholdData 
{ 
    std::map<std::string , double>thresholds; 

    public: 
     O2Threshold(const double & _toxicThres , const double & _lowThres , const double & _elecChemThres) 
     { 
      thresholds["toxic"] = _toxicThres; 
      thresholds["low"] = _lowThres; 
      thresholds["elecchem"] = _elecChemThres; 
      cout << "O2Threshold: " << _toxicThres << " " << thresholds["low"] << " " << thresholds["elecchem"] << endl; 
     } 
}; 

template<typename ThresholdMixin> //CO2Threshold , O2Threshold , or others ... 
class ThresholdSensor : public ThresholdMixin //mixin for BaseSensor 
{ 
    public: 
     ThresholdSensor (BaseSensorData * bsd 
         , std::tuple<size_t , double , double , double , double> && tp) 
      : ThresholdMixin 
       (std::get<2>(tp) 
       , std::get<3>(tp) 
       , std::get<4>(tp) 
       ) 
     { 
      cout << "ThresholdSensor: " << std::get<0>(tp) << " " << bsd->sensorName << " " 
       << std::get<1>(tp) << " " << std::get<2>(tp) << " " << std::get<3>(tp) << " " << std::get<4>(tp) 
       << endl; 
     } 

}; 

template<typename ... SensorType> 
class BaseSensor : public BaseSensorData , public SensorType ... //to my BaseSensor class 
{ 
    size_t windowSize; 
    public: 
     template<typename ... Args> 
     BaseSensor(const string& _sensorName , Args && ... args) 
      : BaseSensorData(_sensorName) 
      , SensorType(this , std::forward<Args>(args))... 
      , windowSize(0U) 
     { 
      std::tuple<Args...> arr[sizeof...(SensorType)] = { args ... }; //line A 
      /*for (size_t i = 0; i < sizeof...(SensorType); ++i) 
      { 
       for (size_t i = 0; i < sizeof...(Args); ++i) 
       { 
        // do stuff 
       } 
      }*/ 
      cout << "BaseSensor: " << /*_windowSize << " " << */sensorName << " " << endl; 
     } 

}; 

int main() { 
    BaseSensor<ThresholdSensor<O2Threshold> , TrendSensor, EdgeSensor>bs 
    { 
     string("testSensor") 
     , std::make_tuple<size_t , double , double , double , double>(54U , 2.5f , 10000.3f , 400.5f , 200.3f) 
     , std::make_tuple<size_t , double >(53U , 6.5f) 
     , std::make_tuple<size_t , double >(52U , 3.5f) 
    }; 

    /*BaseSensor<ThresholdSensor<CO2Threshold> , TrendSensor, EdgeSensor>bs5 
    { 
     string("testSensor") 
     , std::make_tuple<size_t , double , double , double , double>(54U , 2.5f , 10000.3f , 400.5f , 200.3f) 
     , std::make_tuple<size_t , double >(53U , 6.5f) 
     , std::make_tuple<size_t , double >(52U , 3.5f) 
    };*/ 
    //BaseSensor<ThresholdSensor<CO2Threshold> > bs2{string("test"),11U , 12.5f}; 
    //BaseSensor<TrendSensor> bs3{string("test"), 8U , 10.5f}; 
    //BaseSensor<EdgeSensor> bs4{string("test"), 6U , 18.5f}; 

} 

Ainsi, dans "BaseSensor" les tuples de tous mixins (par exemple les "SensorTypes ...") sont transmis à travers le pack paramètre "args ...". Cela fonctionne bien, mais j'ai besoin dans le corps BaseSensor::BaseSensor() pour avoir accès à ces tuples. La syntaxe pour le faire m'échappe cependant.

comment puis-je développer en même temps SensorType ... et Args ... et de classer les "args" selon tuple? Avec le code ci-dessus, j'obtiens ce qui suit en g ++ v4.7.1 et C++ 11 ENABLED:

varcon.cpp:104:64: error: could not convert ‘args#0’ from ‘std::tuple<long unsigned int, double, double, double, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’ 
varcon.cpp:104:64: error: could not convert ‘args#1’ from ‘std::tuple<long unsigned int, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’ 
varcon.cpp:104:64: error: could not convert ‘args#2’ from ‘std::tuple<long unsigned int, double>’ to ‘std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >’ 
varcon.cpp:108:59: error: incomplete type ‘std::tuple_size<std::tuple<std::tuple<long unsigned int, double, double, double, double>, std::tuple<long unsigned int, double>, std::tuple<long unsigned int, double> >&>’ used in nested name specifier 
+0

Votre code compile avec mon g ++ 4.9.2 et mon clang ++ 3.5; donc je suppose que vous devriez mettre à jour le compilateur vers une version plus récente (ps: la sortie du programme compilé est (# rapresent un retour chariot) "O2Threshold: 10000.3 400.5 200.3 # ThresholdSensor: 54 testSensor 2.5 10000.3 400.5 200.3 # TrendSensor: 53 testSensor 6.5 # EdgeSensor: 52 testSensor 3.5 # BaseSensor: testSensor ") – max66

+0

@ max66 salut là. En effet mon code compilé bien. J'ai dû décommenter une ligne dans le corps des constructeurs. Il est mis à jour maintenant – nass

+0

Je vois ... mais mon g ++ et mon clang ++ se compilent avec Line A (déclaration 'arr') aussi; seulement un avertissement évident: "variable inutilisée 'arr'" – max66

Répondre

1

Que voulez-vous obtenir avec l'instruction suivante?

std::tuple<Args...> arr[sizeof...(SensorType)] = { args ... }; 

Le pack Args... est un chemin de differents types std::tuple; donc votre arr est un tableau de tuples de tuples; il faut donc le nourrir avec une suite de tuples de tuples. Mais le paquet args... c'est seulement un paquet de tuples, pas de tuples de tuples.

Ainsi l'erreur de mon clang ++

tmp_002-11,14,gcc,clang.cpp:93:64: error: no viable conversion from 
     'tuple<unsigned long, double, double, double, double>' to 
     'tuple<std::tuple<unsigned long, double, double, double, double>, 
     std::tuple<unsigned long, double>, std::tuple<unsigned long, double>, 
     (no argument), (no argument)>' 

Je suppose que vous pourriez jeter la partie de tableau et définir arr comme

std::tuple<Args...> arr { args ... }; 

Ensuite, si vous souhaitez accéder aux éléments simples, vous pourrait écrire quelque chose comme

std::get<0>(std::get<1>(arr)); 

où le premier std::get (l'interne) l'accès à un tuple (l'un des args...) et le deuxième accès std::get (le plus externe) à un élément du tuple (size_t ou double).