#c
#c
Вопрос:
У меня есть следующий код, который пытается сгенерировать случайную шестнадцатеричную цифру.
#include <random>
#include <functional>
using std::mt19937;
using std::uniform_int_distribution;
class
RandomHexDigitGenerator
(
public :
// Other functions omitted for the sake of brevity.
RandomHexDigitGenerator
(
);
char
generateRandomHexDigit
(
);
private :
mt19937 * rng_p;
mt19937::result_type seed;
uniform_int_distribution<int> * distribution_p; // Map values onto range [0, 15]
// The following declaration will cause a problem since
// the compiler won't be able to deduce its type.
auto rhvg;
);
Определения двух методов следующие;
// Constructor for class.
RandomHexDigitGenerator::RandomHexDigitGenerator
(
)
{
this->seed = time(0);
this->rng_p = new mt19937(this->seed);
this->distribution_p = new uniform_int_distribution<int>(0, 15);
// The following line of code will also be problematic.
this->rhvg = std::bind(* this->distribution_p, * this->rng_p);
}
char
RandomHexDigitGenerator::generateRandomHexDigit
(
)
{
int randomHexValue;
randomHexValue = this->rhvg();
return(this->convertHexValueToHexDigit(randomHexValue));
}
Моя проблема с кодом заключается в операции привязки, которая выполняется в конструкторе. Я не знаю, каков его возвращаемый тип, поэтому я объявляю rhvg как auto . Проблема в том, что, насколько я понимаю, компилятор должен иметь возможность определять тип rhvg, когда он впервые сталкивается с ним в объявлении класса!
Итак, мой вопрос в том, как я могу решить эту проблему? Будет ли тип, возвращаемый операцией привязки, ужасным, и, следовательно, я даже не должен пытаться понять, что это такое? Должен ли я продолжать использовать auto, но другим способом? Является ли шаблонизация класса опцией или шаблонизация является сложным решением для не такой сложной проблемы?
В случае, если это имеет значение, я использую GNU g под Linux Mint версии 19.2, и вывод g -v
команды выглядит следующим образом;
Using built-in specs.
COLLECT_GCC=g
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.10' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c ,java,go,d,fortran,objc,obj-c --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10)
Наконец, мой Makefile использует переключатель -std=c 11
компилятора в правильном месте.
Заранее благодарю.
Комментарии:
1. Я предполагаю, что вы имеете в виду std::bind. Пожалуйста, добавьте, какой компилятор вы используете и какую версию C (если вы ее знаете). Как это выглядит, возвращаемый тип std::bind не является или не всегда был частью спецификации C . Кроме того, пожалуйста, добавьте то, что вы уже сделали, чтобы получить ответ.
2. Зачем вам использовать
std::bind
здесь, с объектами известного типа и вызовом, которым вы управляете? Просто вызывайте дистрибутив с генератором, когда вам нужно, нет?3. Не имеет отношения к вопросу, но почему все пустые строки? Кроме того, вам не нужно писать
this->
везде и не заключать возвращаемые выражения в скобки.
Ответ №1:
Ваш код намного более запутанный и подробный, чем мне удобно. Вот что я бы сделал:
#include <random>
#include <ctime>
class RandomHexDigitGenerator
{
public:
char generateRandomHexDigit() {
return static_cast<char>(dist(rng));
}
private:
std::mt19937 rng{static_cast<std::mt19937::result_type>(std::time(0))};
std::uniform_int_distribution<int> dist{0, 15};
};
Нет new
, нет bind
.
Возвращаясь к поставленному вопросу, у вас не может быть нестатического члена класса типа «неизвестный результат привязки». Вместо этого вы можете иметь std::function
, но это не имеет никакого смысла, вот почему.
bind
сохраняет свои аргументы путем копирования, поэтому, если вы сделаете это
std::function<char(void)> rhvg;
rhvg = std::bind(distribution, rng);
вам больше не нужны distribution
rng
члены and, потому что они копируются в bind
. Таким образом, вы можете создать их в конструкторе вместо этого.
class RandomHexDigitGenerator
{
public:
char generateRandomHexDigit() {
return rhvg();
}
private:
std::function<char(void)> rhvg = std::bind(
std::uniform_int_distribution<int>(0, 15),
std::mt19937(static_cast<std::mt19937::result_type>(std::time(0)))
);
};
но зачем для этого нужен класс? Вместо этого вы можете обернуть все в функцию:
std::function<char(void)> makeRandomHexDigitGenerator() {
return std::bind(whatever);
}