Basti
Basti

Reputation: 2438

C++ function template, mix implicit and explicit instantiation?

So I want to write a function that measures the runtime of a random number generation. To be able to use different random engines and distributions, I use templates for those, but I also need a template parameter to initialize the vector I write the numbers in.

    template<typename T_rng, typename T_dist, typename T_vectype>
    double timer_gen(T_rng& rng, T_dist& dist, int n){
        std::vector< T_vectype > vec(n, 0);
        auto t1 = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < n; ++i)
            vec[i] = dist(rng);
        auto t2 = std::chrono::high_resolution_clock::now();
        auto runtime = std::chrono::duration_cast<std::chrono::microseconds>(t2-t1).count()/1000.0;
        return runtime;
    }

    int main(){
        const int n = 1000;
        unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
        std::minstd_rand rng_minstd (seed);
        std::uniform_real_distribution<double> dist_double(0.0, 1.0);
        double runtime_double_minstd = timer_gen<std::minstd_rand, std::uniform_real_distribution<double>, double>(rng_minstd, dist_double, n);
    }

This works! But I feel like there must be a better way for the last line. the first two template parameters could be deduced implicitly, I only need to list them because the third needs to be set to int. Is there a better way to do this?

Upvotes: 1

Views: 845

Answers (2)

David G
David G

Reputation: 96790

One option is to rearrange the order of the template parameters so that the value_type of the vector is specified first. Another option is to set T_vectype as a default template parameter to typename T_dist::result_type which is the exposed typedef aliasing the type you specified for the random number generator.

Upvotes: 1

Yes, change the order of the parameters:

template<typename T_vectype, typename T_rng, typename T_dist>
double timer_gen(T_rng& rng, T_dist& dist, int n){
  // .. as before
}

int main(){
    const int n = 1000;
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::minstd_rand rng_minstd (seed);
    std::uniform_real_distribution<double> dist_double(0.0, 1.0);
    double runtime_double_minstd = timer_gen<double>(rng_minstd, dist_double, n);
}

If you specify less explicit template arguments than there are template parameters, the compiler will (try to) deduce the rest. That also covers the case of "no arguments specified explicitly."

Upvotes: 1

Related Questions