2016-06-15 3 views
1

コンパイル時に型またはペアの要素を推定するにはどうすればよいですか?引数の型に応じて正しいインスタンスを作成する必要があります(例えば、real_random_generator double、floatおよびその他の浮動小数点の場合、long、int、unsigned intなどのInteger_random_generatorの場合)。私はあなたがコメントアウトされた行63〜77で見ることができるように、特定の範囲で発電機を作る必要があります。実行時に基礎となるタプル型に基づいて要素を生成する

#ifndef OPTIMALIZATION_HPP 
#define OPTIMALIZATION_HPP 

    #include<utility> 
    #include<random> 
    #include<experimental/random> 
    #include<functional> 
    #include<experimental/functional> 
    #include<experimental/tuple> 
    #include<algorithm> 
    #include<type_traits> 
    #include<iostream> 

    #include"tuple_for_each.hpp" 

    //ZNAJDZ/ZROB INDEKSOWANY DOSTEP DO TUPLI W CZASIE RUN-TIME'U 
    namespace numerics{ 
     template< 
      std::size_t population_size, std::size_t generations, 
      typename Func, 
      typename Compare, //GREATER, LESS, TYPE RETURNED BY FUNCTION 
      typename Generator=std::default_random_engine, 
      template<typename> 
       typename RealDistribution=std::uniform_real_distribution, 
      template<typename> 
       typename IntegerDistribution=std::uniform_int_distribution, 
      typename ...Ts 
     > 
     auto optimize(
       const Func& function, const Compare& comp, 
       const std::pair<Ts,Ts>&... range 
     ){ 

      std::size_t range_argument_count=sizeof...(range); 
      static_assert(range_argument_count>2, 
        "Function needs at least two range arguments" 
      ); 

      //RANDOM NUMBER GENERATORS 
      auto real_random_generator=[&](const std::pair<auto,auto> range){ 
       std::cout << "DOUBLE" << std::endl; 
       return std::bind(
         RealDistribution<long double>(range.first,range.second), 
         //RealDistribution<decltype(range.first)>(range.first,range.second); 
         //HOW TO DEDUCE TYPE OF DISTRIBUTION FROM PAIR DURING COMPILE-TIME??? 
         Generator() 
       ); 
      }; 

      auto integer_random_generator=[&](const std::pair<auto,auto>& range){ 
      std::cout << "INTEGER" << std::endl; 
       return std::bind(
         IntegerDistribution<long long>(range.first,range.second), 
         //IntegerDistribution<decltype(range.first)>(range.first,range.second); 
         //HOW TO DEDUCE TYPE OF DISTRIBUTION FROM PAIR DURING COMPILE-TIME??? 
         Generator() 
       ); 
      }; 
      std::cout << integer_random_generator(std::get<0>(std::make_tuple(range...)))() << std::endl; 
      std::cout << real_random_generator(std::get<1>(std::make_tuple(range...)))()<<std::endl; 
      std::cout << integer_random_generator(std::get<2>(std::make_tuple(range...)))()<<std::endl; 

      //GENERATORS DEPENDING ON TYPE, USED THROUGH WHOLE PROGRAM 
      /*std::tuple<> generators; 
      numerics::for_each(std::make_tuple(range...), [&](std::pair<auto,auto>& x){ //FOR_EACH SPRAWDZENIA 
        try{ 
         generators=std::tuple_cat(
           generators, 
           std::make_tuple(integer_random_generator(x.first))); 
        } 
        catch(...){ 
         generators=std::tuple_cat(
           generators, 
           std::make_tuple(real_random_generator(x.first))); 
        } 
       } 
      );*/ 
      return "pls work"; 
     } 
    } 
    #endif 

テストケース:

#include<utility> 
#include<iostream> 
#include"optimize.hpp" 

class Function{ 
    public: 
     Function()=default; 
     double operator()(int x, double y, long z)const{ 
      return (std::exp(x+1.25)*std::pow(y,z))/std::exp((x*y)/z); 
     } 
}; 

int main(){ 
    Function f{}; 
    auto comp=std::less<double>(); 
    auto x=numerics::optimize<100, 200>(
      f, comp, 
      std::make_pair(-21, 37), 
      std::make_pair(14.88, 88.41), 
      std::make_pair(-13, 37) 
    ); 
    std::cout << x << std::endl; 

} 
+3

あなたが何から推測したいのかは不明です。あなたはあなたの問題が何であるかを精緻化できますか?より好ましくは、最小限の例である。 – Barry

+1

コメントアウトされたコード 'IntegerDistribution (range.first、range.second);の問題は何ですか?コンパイルエラーが出ますか?もしそうなら、何? – Smeeheey

+0

[mcve]を見て、他の人が理解しやすくするために問題を簡略化する方法についていくつかアドバイスをしてください。 –

答えて

2

実数または整数ジェネレータを作成するかどうかを決定するためにヘルパー関数を書きます。この場合、範囲内の最初のパラメータの型に基づいています。 2番目のパラメータもチェックする方法を決定するために、私はあなたに任せます。 (私はこのコードをテストしていませんが、そのアイデアが機能していると確信しています)。

template <class Range> 
auto get_distribution(Range range, std::true_type) 
{ 
    return real_random_generator(range); 
} 

template <class Range> 
auto get_distribution(Range range, std::false_type) 
{ 
    return integer_random_generator(range); 
} 

単にstd::is_floating_point

auto generators = std::make_tuple(get_distribution(ranges, 
         std::is_floating_point<decltype(ranges.first)>{})...); 

すべての範囲であなたのヘルパー関数を呼び出すためにパック拡張構文を使用し、過負荷が各範囲のために呼び出されるかを判断するものです。

あなたは、トリッキーが、より簡潔なコードのようにあなたはこれを試してみることができる場合:

auto fs = std::make_tuple(integer_random_generator, real_random_generator); 
auto generator = std::make_tuple(std::get<std::is_floating_point<decltype(ranges.first)>::value>(fs)(ranges)...); 

はあなたのジェネレータ生成ラムダのタプルを構築(彼らはオブジェクトではありませんでした場合、これは動作しないでしょう)とこの条件をタプルのインデックスとして使用し、すぐに呼び出します。私はこれを使用することを主張していないが、私はそれにもかかわらずそれを共有すると思った。

+0

トリッキーなものは本当に素晴らしいアイデアですが、範囲の代わりに範囲を指定する必要があります。第2行目、第2引数、それ以外は完璧です、ありがとう! – MostLovelyRollOnThePlanet

+0

@MostLovelyRollOnThePlanet私はちょうど私がコピーした元の投稿のバグだと思う。それを指摘してくれてありがとう。 – SirGuy

関連する問題