C++ 在知道其类型之前使用自动定义的变量

C++ Using an auto-defined variable before knowing its type

我目前正在尝试在不知道其类型之前使用自动定义的变量。为什么?因为类型取决于程序输入。如果用户选择某个分布,程序将根据该分布输出值。这是代码:

std::default_random_engine random_engine;
auto random;

if(from_dist)
{
    char* dist_name = strtok(distribution_name, "()");
    char* parameters = strtok(nullptr, "()");
    if(strcmp(dist_name, "gaussian") == 0)
    {
        double mean = atof(strtok(parameters, ","));
        double stddev = atof(strtok(nullptr, ","));
        std::normal_distribution<double> normal_distribution(mean, stddev);
        random = std::bind(normal_distribution, random_engine);
    }
        //TODO: Add more...
    else
    {
        std::cerr << "Invalid distribution. Known distributions:" << std::endl;
        std::cerr << "\tgaussian(mean,stddev) - gaussian (aka normal) distributions" << std::endl;
        exit(EXIT_FAILURE);
    }
}

但是,C++ 不允许我以这种方式使用自动变量。是否有任何替代方案可以让我使用以下代码片段(稍后执行),而不必为每个可能的分布重复它?

while(true) {
        std::string message(OBSERVATION);
        for (int i = 0; i < FEATURE_COUNT; i++)
            message += " " + ((int) random());

        send(sock, message.c_str(), strlen(message.c_str()), 0);
        if (wait_time_ms)
            sleep(wait_time_ms);
}

random(如果我没看错你的代码)的目的是成为一个可调用对象。

您可以通过使 random 成为具有正确签名的 std::function 对象来解决您的问题:

std::function<double()> random;

auto 声明的变量类型必须 编译时 是已知的。如果您真的想要使用单个变量名称存储不同类型的值,请查看具有正确签名的 std::variant. However, it does also look like you don't even need to use multiple types. If I understand your code correctly, random should be declared as an std::function 对象。

为了使用 auto,您必须初始化变量,以便编译器可以推断类型。由于您不确定要使用哪种类型,因此无法使用它。由于所有随机生成器都具有 double() 的形式,因此您可以做的是使用 std::function<double()>。这将允许您在需要的范围内声明 random 但允许您为其分配所需的生成器。看起来像

std::default_random_engine random_engine;
std::function<double()> random;

if(from_dist)
{
    char* dist_name = strtok(distribution_name, "()");
    char* parameters = strtok(nullptr, "()");
    if(strcmp(dist_name, "gaussian") == 0)
    {
        double mean = atof(strtok(parameters, ","));
        double stddev = atof(strtok(nullptr, ","));
        random = [=]()
        { 
            static std::normal_distribution<double> normal_distribution(mean, stddev);
            return normal_distribution(random_engine);
        };
    }
    //...
}