2016-09-25 3 views
0

私は "BaseSensor"ホストクラスのさまざまなミックスインに様々なstd::tuplesを転送するのにうまく動作する次のコードを持っています。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}; 

} 

だから、「BaseSensor」内のすべてのミックスイン(すなわち「SensorTypes ...」)のタプルは「Argsの...」パラメータパックを介して転送されます。これはうまく動作しますが、私はBaseSensor::BaseSensor()本体でこれらのタプルにアクセスする必要があります。しかし、それを行うための構文は私を逃す。

私は同時にどのように拡大することができますSensorType ...Args ...とタプルに従って "args"を分類しますか?上記のコードでは は、私がg ++ v4.7.1およびC++ 11が有効で、次を得る:

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

あなたのコードは、g ++ 4.9.2と私のclang ++ 3.5でコンパイルします。コンパイルされたプログラムの出力は、(#復帰すると致命的なエラーになります) "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こんにちは。実際、私のコードはうまくコンパイルされました。私はコンストラクタボディの行のコメントを外さなくてはなりませんでした。これは今更新されました – nass

+0

私は参照してください...しかし、私のg ++​​と私のclang ++は、ラインA( 'arr'宣言)でもコンパイルします。 "未使用の変数 'arr'" – max66

答えて

1

次の命令を取得したいですか?

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

パックは貴様std::tupleタイプのパスです。あなたのarrはタプルのタプルの配列です。そのため、タプルの一連のタプルをフィードに追加する必要があります。しかし、args...はタプルのパックであり、タプルのタプルではありません。

だから私はあなたが単一の要素にアクセスしたい場合は、あなたの次の配列の一部を捨ててarr

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

を定義することができたと++

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)>' 

私の打ち鳴らすからのエラー何かを書くことができる

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

ここで最初のタプル(args...の1つ)とタプルの要素(size_tまたはdouble)への2番目のstd::get(より外部の)アクセスへのアクセスは、(内部のもの)です。

関連する問題