Ну, вы можете сделать свою собственную функцию, но остерегайтесь следующего. Каждое число должно быть нарисовано с равной вероятностью. Вам нужно будет определить, из какого диапазона будет получено число с вероятностью, пропорциональной размеру диапазона, например, Рисование из [1,10], [21, 40] должно составлять числа из [21,40] примерно в два раза чаще, чем из [1,10].
Вот общая идея:
Определить длину всех диапазонов.
Нарисуйте случайное число от 0 до длины всех диапазонов.
Проверьте, к какому диапазону относится число.
Нарисуйте соответствующее число из диапазона, в котором оно находится.
function randFromRanges(...$ranges) {
$totalRangeSize = array_sum(array_map(function ($range) {
return $range[1] - $range[0];
}, $ranges));
$numberToDraw = rand(0, $totalRangeSize);
foreach ($ranges as $range) {
if ($numberToDraw <= ($range[1] - $range[0])) {
return $range[0]+$numberToDraw;
} else {
$numberToDraw -= ($range[1] - $range[0]);
}
}
}
Вот песочница, которая показывает, что все значения кажутся равноправными:
http://sandbox.onlinephpfunctions.com/code/b02603e4a9986132073d203c98f8255c2dd62e47
Опция 1: удостоверьтесь, что все различные типы аргументов происходят из базового класса и используют указатели на тот класс. Обратите внимание, что эта опция опасна с точки зрения управления памятью. Вы могли бы хотеть сделать это более безопасным при помощи повышения:: shared_ptr вместо указателей. Иначе необходимо вручную вымыться, когда объект удаляется из вектора.
Опция 2 (мой любимый): используйте Повышение. Вариант, чтобы сделать определение типа всех возможных типов аргумента и использовать то определение типа в качестве типа аргумента в станд.:: вектор
typedef boost::variant<ArgumentType1, ArgumentType2, ArgumentType3> ArgumentType;
std::vector<ArgumentType> vec;
Вы могли использовать повышение:: вариант (http://www.boost.org/doc/libs/1_38_0/doc/html/variant.html)
или повышение:: любой (http://www.boost.org/doc/libs/1_38_0/doc/html/any.html) типы
или пусто* - ужасный и не безопасный с точки зрения типов
или реализация владеет универсальным типом, который будет иметь один интерфейс и другую шаблонную реализацию и сохранит указатель в этом интерфейсе.
Но я не уверен, что использование подобных типов является хорошим дизайном.
Самый легкий способ сделать это должно было бы иметь основной класс Аргумента, который не является шаблонным, и затем имейте определенные типы данных, происходят из него. (Вы могли даже заставить шаблонную версию произойти из базового класса непосредственно и просто использовать те два класса.) Затем Вы храните их как указатели в векторе.
Это действительно требует, чтобы наличие своего рода функций получило доступ к значениям аргументов и выполнило любые преобразования как требуется.