2010-11-15 8 views
1

У меня есть простой константный метод, который хочет, чтобы сгенерировать случайное числоC++ TR1: Каков правильный способ использования равномерного распределения для генерации случайного числа в методе const?

int Object::const_method() const { 
    std::tr1::uniform_int<int> uni(0,100); 
    // do some calculation 
    return result; 
} 

Это приводит к вашему стандарту (если templafied) Const ошибки нарушения

/usr/lib/gcc/x86_64-unknown-linux-gnu/4.5.1/../../../../include/c++/4.5.1/tr1/random.tcc:910:4: error: passing ‘const std::tr1::mersenne_twister’ as ‘this’ argument of ‘result_type std::tr1::mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, __b, __t, __c, __l>::operator()() [with _UIntType = long unsigned int, int __w = 32, int __n = 624, int __m = 397, int __r = 31, _UIntType __a = 2567483615ul, int __u = 11, int __s = 7, _UIntType __b = 2636928640ul, int __t = 15, _UIntType __c = 4022730752ul, int __l = 18, result_type = long unsigned int]’ discards qualifiers

Является ли это выполнимо без const_cast на this?

+2

Если ваш PRNG является элементом данных, тогда сделайте его «изменчивым» или удерживайте указатель вместо объекта. –

+1

Опубликуйте полный исходный код. По внешнему виду ошибки ваша проблема находится в части «// сделать некоторые вычисления», которую вы исключили. А именно часть, в которой вы используете объект _uni_. – Akusete

+0

Кстати: вы никогда не должны использовать const casting, если не уверены, что переменная, о которой идет речь, никогда не записывается, иначе поведение не определено и ** WILL ** ломается с оптимизацией/многопоточным. – Akusete

ответ

1

Сделайте свой объект mersenne_twister изменчивым в своем классе. Не видя всего вашего кода (особенно часть do_something), мы не можем быть уверены, но я предполагаю, что у вас есть объект в вашем классе типа merseene_twister, который вы используете, функция которого не является самой функцией const , Это вызывает ошибку в вашем классе, потому что ваша функция const вызывает функцию merseen_twister, которая может ее изменить, нарушая вашу подпись const.

// I'm using this as an example. Yours may differ 
typedef std::mersenne_twister<unsigned int, 32, 624, 
    397, 31, 0x9908b0df, 11, 7, 0x9d2c5680, 
    15, 0xefc60000, 18> MerTwister; 

class Object 
{ 
    public: 

    int Object::const_method() const 
    { 
     std::tr1::uniform_int<int> uni(0,100); 

     // do some calculation using the MerTwister object 
     return result; 
    } 


    private: 
    mutable MerTwister twister; 
}; 
+0

Ах спасибо, забыли про изменяемое ключевое слово. – Casey

+2

@ Casey: Я не уверен, что это обязательно лучшее решение здесь (хотя оно, очевидно, работает). 'mutable' предназначен для помощи в ситуациях, когда содержащий объект является логически постоянным, но для реализации требуется модификация (например, подсчет ссылок, ленивая оценка). Однако в сценарии OP вызов 'const_method()' действительно изменяет объект видимым образом (он не чист, если хотите). ИМХО, лучшим решением не является 'const_method()', объявленный как 'const'. –

+0

@ Oli: Hm, вот сценарий, поэтому вы можете сказать мне, что вы думаете: 'const_method' is' Position unoccupied_pos() const'. Он возвращает случайную незанятую позицию в плоскости 2d. Он используется для случайного распределения некоторых 2d объектов по всей плоскости. Мне кажется, что он не модифицирует какое-либо внутреннее состояние (кроме движка), не считается ли оно логически постоянным? – Casey