Использование C ++ 0x TR1 случайных в классе для низких накладных расходов - PullRequest
4 голосов
/ 16 октября 2010

Я использую VC 2010 и пытаюсь сохранить накладные расходы и дублированный код некоторых функций на низком уровне, помещая случайные определения в конструктор каждого экземпляра класса, а затем вызывая их по мере необходимости. То, что я имею сейчас, упрощенно, это:

#include <random>
#include <Windows.h>
mt19937 eng(GetTickCount());

class Cycles {
    int line;
    normal_distribution<> rand_norm;
    variate_generator<mt19937&,normal_distribution<>> r_norm;
public:
    Cycles() 
    : rand_norm(0.85,0.05),
      r_norm(eng,rand_norm) { 
        line=0; 
    }
}

К сожалению, это не работает, и я получаю эту ошибку:

\ vc \ include \ random (513): ошибка C2248: 'std :: tr1 :: _ Ewrap <_Engine, _Tgt_type> :: operator =': невозможно получить доступ к закрытому члену, объявленному в классе 'std :: tr1 :: _ Ewrap <_Engine, _Tgt_type> '

\ vc \ include \ random (446): см. Объявление 'std :: tr1 :: _ Ewrap <_Engine, _Tgt_type> :: operator ='

Эта диагностика произошла в сгенерированной компилятором функции 'std :: tr1 :: variate_generator <_Engine, _Distrib> & std :: tr1 :: variate_generator <_Engine, _Distrib> :: operator = (const std :: tr1 :: variate_generator < _Engine, _Distrib> &) '

Я понимаю, что они должны быть инициализированы до открытия конструктора, иначе произойдет ошибка из-за отсутствия конструктора по умолчанию, но я не понимаю, почему это не удается. Мой С ++ фу довольно ржавый.

Каждый пример, который я видел, показывает, что распределитель и генератор инициализируются глобально или локально в вызывающей его функции, что мне кажется глупым, поскольку у меня есть несколько функций-членов, которые будут использовать r_norm, которые вызываются в узком цикле , Это плохо проходит тест на запах. Неужели никто не знает, что мне не хватает?

Ответы [ 3 ]

6 голосов
/ 16 декабря 2010

bind() используется в c ++ 0x вместо variate_generator<>:

#include <functional> // bind
#include <iostream>
#include <vector>
#include <random>

namespace {
  std::random_device generate_seed;
  std::mt19937 eng(generate_seed());    
  class Cycles {
    int line;
    std::normal_distribution<> rand_norm;
    std::function<double()> r_norm;
  public:
    Cycles(): line(0), rand_norm(0.85, 0.05), r_norm(std::bind(rand_norm, eng))
    {
      // print distribution
      std::vector<size_t> freq(200);
      for (int i = 0; i < 900; ++i) ++freq.at(std::round(r_norm()*100));

      size_t line = 0, max_line = freq.size()-1;
      for ( ; not freq[line] and line <= max_line;  ++line);
      for ( ; not freq[max_line] and max_line >= line; --max_line);
      for ( ; line <= max_line; ++line) {
        std::cout << line << '\t';
        for (size_t j = 0; j < freq[line]; ++j) std::cout << '*';
        std::cout << std::endl;
      }
    }
  };
}    
int main() {
  Cycles c;
}

Сюжет вдохновлен C ++ 0xFAQ .

Выход

72 **
73 ***
74 ******
75 ********
76 *****************
77 ********************
78 *******************************
79 ************************************************
80 *************************************************
81 **********************************************************
82 ************************************************************
83 ***********************************************************
84 ************************************************************************
85 ********************************************************************************
86 *********************************************************************
87 ************************************************************
88 ****************************************************
89 *************************************
90 **********************************
91 **************************************
92 *************************
93 ******************
94 ********************
95 ************
96 ****
97 **********
98 ***
99 **
100 **
101 *
3 голосов
/ 16 октября 2010

нет MSVC под рукой, но с gcc, это скомпилируется, если вы замените

variate_generator<mt19937&,normal_distribution<>> r_norm;

на

variate_generator<mt19937, normal_distribution<> > r_norm;

(обратите внимание на отсутствие &)

Кстати, std::random_device, вероятно, лучший источник случайности, чем GetTickCount(), хотя я не знаю, как это реализовано в MSVC.

0 голосов
/ 16 октября 2010
mt19937 eng(GetTickCount());

Нельзя инициализировать глобальную переменную нестатическим выражением.

...