I'm trying to create a std::discrete_distribution object using data passed into a class constructor. I know how to create this using static data, but cannot figure out how using variable data (cleanly). What I have now "works", but is painful. Is there a more appropriate way of doing this?
The distInit = { distArray[0], ... }; line is the problem.
#include <iostream>
#include <iomanip>
#include <initializer_list>
#include <map>
#include <random>
class Die {
private:
int loadSide;
double loadAmount;
std::mt19937 generator;
std::discrete_distribution<> distribution;
std::initializer_list<double> distInit;
std::array<double, 7> distArray;
public:
Die( int loadSide, double loadAmount ) : loadSide(loadSide), loadAmount(loadAmount) {
distArray.fill( 1 );
distArray[0] = 0;
distArray[this->loadSide] = this->loadAmount;
distInit = { distArray[0], distArray[1], distArray[2], distArray[3], distArray[4], distArray[5], distArray[6] };
distribution.param( distInit );
};
int roll( ) {
return distribution( generator );
};
};
const int ROUNDS = 10000;
int main() {
Die* die = new Die( 5, 20 );
std::map<int, int> m;
for(int n=0; n < ROUNDS; n++) {
m[die->roll()]++;
}
for(auto p : m) {
std::cout << p.first << " generated " << std::setiosflags(std::ios::fixed) << std::setprecision(2) << (float) p.second / ROUNDS << " times\n";
}
}
I may not be asking the right question, which I will apologize in advance for if so. This is a strong possibility as I'm surprised I'm unable to find any (apparently) related hits on this subject.
My compiler is g++-mp-4.8 (MacPorts gcc48 4.8-20130411_0) 4.8.1 20130411 (prerelease)
Command line /opt/local/bin/g++-mp-4.8 -std=c++11 test.cpp -o test
If you have variable data, you should be using the discrete_distribution constructor taking a pair of iterators:
template< class InputIt >
discrete_distribution( InputIt first, InputIt last );
You shouldn't be trying to construct the param_type directly; instead use a helper function to construct your distribution:
class Die {
private:
std::mt19937 generator;
std::discrete_distribution<> distribution;
static std::discrete_distribution<> makeDistribution(
int loadSide, double loadAmount )
{
std::array<double, 7> distArray;
distArray.fill( 1 );
distArray[0] = 0;
distArray[loadSide] = loadAmount;
return {std::begin(distArray), std::end(distArray)};
}
public:
Die( int loadSide, double loadAmount ) :
generator{ },
distribution{ makeDistribution( loadSide, loadAmount ) }
{}
int roll( ) {
return distribution( generator );
}
};
std::initializer_list only intended for use as a temporary object (function argument) or local variable. It's not a container and it doesn't own anything; it's an accessor to an anonymous, temporary array.
The Standard includes an example similar to your code, §8.5.4/6, which mentions
the initializer_list object is initialized in a constructor’s ctor-initializer, so the array persists only until the constructor exits, and so any use of the elements of i4 after the constructor exits produces undefined behavior.
In your case, it's the body of the constructor, not a ctor-initializer preceding the body, but the story is the same. It's just dumb luck that your program is working for now.
To store the distribution in the object, use std::array or std::vector. array is more efficient but it doesn't support arr = { … } syntax. (There are a few simple alternatives.) vector does support your syntax using braces and the = operator; this support uses an implicit std::initializer_list.
I don't know any better way to create a std::initializer_list from a container like std::array other than the one shown in the OP.
However, for the original problem, namely, passing the parameters to the distribution, I can suggest something simpler.
typedef std::discrete_distribution<>::param_type param_type;
distribution.param(param_type(distArray.begin(), distArray.end()));
The standard says that distributions must provide a type member param_type (which is the type of argument taken by param()) but doesn't specify it. However, [rand.req.dist] says that
For each of the constructors of D [the distribution type] taking arguments corresponding to parameters of the distribution, P [param_type] shall have a corresponding constructor subject to the same requirements and taking arguments identical
in number, type, and default values.
Well, it turns out that std::discrete_distribution<> has a constructor taking iterators pointing to the range of parameters. Therefore, whatever std::discrete_distribution<>::param_type is, it must have a similar constructor. Therefore, I'm suggesting creating a param_type from distArray.begin() and distArray.end() and pass it to distribution.param().
A side note: You no longer need std::initializer_list<double> distInit; in your class. It seems to me that you don't need std::array<double, 7> distArray as a class member either (it could be a local variable in Die's constructor).
Related
I would like to store the value that is passed to the constructor in a static set returned by a static function.
It seems that the insertion is successful, but when it reach the end of the scope of the constructor it disappear.
I have reproduced it in a simple example:
// container.hh
#pragma once
#include <vector>
#include <set>
class container {
public:
container(const int& s);
static std::set<int, std::less<int>>& object_set_instance();
};
#include "container.hxx"
// container.hxx
#pragma once
#include "container.hh"
#include <iostream>
container::container(const int& s)
{
auto set = object_set_instance();
set.insert(s);
std::cout << "Size " << set.size() << "\n";
}
std::set<int, std::less<int>>& container::object_set_instance()
{
static std::set<int, std::less<int>> s;
return s;
}
#include "container.hh"
#include <iostream>
int main()
{
auto a = container(42);
auto b = container(21);
auto b1 = container(51);
auto b2 = container(65);
auto b3 = container(99);
}
Output :
Size 1
Size 1
Size 1 // Size never change
Size 1
Size 1
Why doesn't the set's size change ?
auto set = object_set_instance();
If you use your debugger to inspect what set is, you will discover that it's a std::set and not a std::set& reference. Effectively, a copy of the original std::set is made (object_set_instance() returns a reference, only to copy-construct a new object that has nothing to do with the referenced one), and the next line of code modifies the copy, and it gets thrown away immediately afterwards.
This should be:
auto &set = object_set_instance();
A debugger is a very useful tool for solving these kinds of Scooby-Doo mysteries, and it would clearly reveal what's going on here. If you haven't yet had the opportunity to learn how to use one, hopefully this will inspire you to take a look, and join Mystery, Inc. as a member in good standing.
Shown below is a working code. But I want to use "this" keyword to call my function pointers inside my implementation (e.g inside the constructor implementation). Please help me to come up with a solution.
My system is
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55)
Working Code
#include <iostream>
#include <string>
#include <map>
using namespace std;
class TestClass{
public:
typedef int (TestClass::*FunctionPtr)(int);
map <string, FunctionPtr> mFnPtrMap;
int Function1( int nAdd ) { return nAdd + 1; }
int Function2( int nAdd ) { return nAdd + 2; }
TestClass() {
mFnPtrMap.insert( make_pair( "Function1", &TestClass::Function1) );
mFnPtrMap.insert( make_pair( "Function2", &TestClass::Function2) );
}
int CallFunction( const string & s, int n ) {
FunctionPtr fp = mFnPtrMap[s];
return (this->*fp)(n);
}
};
int main() {
TestClass ts;
cout << ts.CallFunction( "Function1", 0 ) << endl;
cout << ts.CallFunction( "Function2", 0 ) << endl;
}
What I want to do is:
My expectation is to change it into something like this (use 'this->' instead of 'TestClass::')
mFnPtrMap.insert( make_pair( "Function1", &this->Function1) );
It gives me a compiler error. It even suggests me to use TestClass:: name resolution.
"ISO C++ forbids taking the address of a bound member function to form
a pointer to member function. Say &TestClass::Function1"
Does that mean it's not possible? If someone could give me an explanation also, it would help me to understand the theory underneath. Thank you.
If I had to guess for a reason behind this part of the C++ standard, it's that the types of expressions are hardly equivalent. Just compare how you would need to call the function if in a single expression without the function call as some sort of indirection:
(this->*TestClass::function)(); // Binding the member pointer to an instance
Here we bind the member pointer to an instance with the ->* operator which fills the implicit T* argument each member function has, the one named this. Some other language ask you to provide it explicitely, for example Python but I'm sidetracking a bit.
this->function();
Here the subexpression this->function already bound the parameter of this to the local this object which mean that this does in fact in no way refer to a function. Consequently, you can not take an address of it.
You could argue that this should be allowed as part of the standard but consider the fact that you can shadow function declarations in child classes. That means that introducing a second expression for expressing &TestClass::function would only introduce confusion. In the current form it is very clear which function we are referring to whereas in a this->function form it would not be, especially newcomers might assume that this is completely dynamic as this is not a static object. It would also not be interely unreasonable to assume that there in fact is a difference between the expressions.
In the mean time, I can only offer a way to remove the explicit referal to the class by some type level computations:
#include <type_traits>
template<typename T>
using This = typename std::remove_const<typename std::remove_pointer<T>::type>::type;
TestClass::TestClass() {
mFnPtrMap.insert( make_pair( "Function1", &This<decltype(this)>::Function1) );
mFnPtrMap.insert( make_pair( "Function2", &This<decltype(this)>::Function2) );
}
(Rephrased the question)
I'm creating a wrapper class for boost normal distribution, and want to make it as efficient as possible.
If I use:
double x = 0.0;
boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor(rng, nd);
for (int i=0; i<20; i++) {
double x = var_nor();
}
The loop works fine. My concern is that I don't want to be declaring anything unnecessarily as the method gets called many times. I tried splitting up the code and put this line in the constructor:
boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor(rng, nd);
and have a sample method that does this:
double x = var_nor();
return x;
But in this case, I get an error saying var_nor() (ie. with no arguments) is not found.
Can anyone tell me what's going on with these boost declarations ie. what does the
boost:variate_generate etc.
line actually do in with var_nor?
With my limited C++ knowledge, it looks as if var_nor is being defined with two different signatures.
Thanks guys
Pete
In your code, var_nor is a variable, not a function, so it doesn't have a signature. It represents a variate_generator object that can behave like a function because it supports operator().
In your code, you declare and initialize var_nor at the same time. The rng and nd arguments are passed to the constructor of the variate_generator object.
When you moved the declaration into your class's constructor, you were declaring var_nor as a local variable in the constructor, so it's no wonder it wasn't available elsewhere. For something to be available throughout an entire class, it needs to be a member variable. Declare it private in the class:
class NormalDistribution
{
boost::random::mt19937 _rng;
boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor;
public:
NormalDistribution();
};
Then initialize it in the constructor:
NormalDistribution::NormalDistribution():
_rng(), var_nor(_rng, boost::normal_distribution<>(0.0, 1.0))
{ }
The _rng member needs to be declared first so that it will be initialized first. The nd parameter can be omitted and replaced with a temporary normal_distribution object passed directly to the var_nor constructor as shown above.
With those changes, you should be able to use the same normal_distribution object over multiple calls to your sample function, or whatever other uses you have for your NormalDistribution class.
In the code you've since deleted from your question, you were confusing variable declarations with function declarations. You declared nd as a function receiving two parameters and returning a normal_distribution. Likewise with var_nor. It was a function when you really wanted an object. You were confused because it happens to be an object that acts like a function, but it's still just an object.
OK, working final version using Rob Kennedy's answer, for others that might be interested:
// normaldistribution.h
#ifndef NORMALDISTRIBUTION_H
#define NORMALDISTRIBUTION_H
#include <boost/random.hpp>
#include <boost/random/normal_distribution.hpp>
class NormalDistribution
{
public:
NormalDistribution();
double sample(void);
private:
// Use the boost random number generator
boost::mt19937 rng;
// Make a variate_generator OBJECT.
boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor;
};
#endif // NORMALDISTRIBUTION_H
// normaldistribution.cpp
NormalDistribution::NormalDistribution():
rng(), var_nor(rng, boost::normal_distribution<>(0.0, 1.0))
{
std::cout << "Called normal distribution constructor, passing up var_nor" << std::endl;
}
double NormalDistribution::sample(void) {
double x = var_nor();
return x;
}
// main.cpp
#include "normaldistribution.h"
int main(int argc, char *argv[])
{
NormalDistribution *nd = new NormalDistribution();
for (int i=0; i < 10; ++i)
{
double d = nd->sample();
std::cout << d << std::endl;
}
return 0;
}
So I was trying to test a lambda accessing local variables in the scope in which it is used, based roughly on a simple example by Bjarne on the C++0x FAQS page at:
http://www2.research.att.com/~bs/C++0xFAQ.html#lambda
When I try this simple test code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//Test std::fill() with C++0x lambda and local var
void f (int v) {
vector<int> indices(v);
int count = 0;
fill(indices.begin(), indices.end(), [&count]() {
return ++count;
});
//output test indices
for (auto x : indices) {
cout << x << endl;
}
}
int main() {
f(50);
}
I get the error:
required from 'void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >, _Tp = f(int)::<lambda()>]'
I'm supposing this errmsg indicates the std::fill() signature requires a const Type& to use for the new value element assignment.
But if I'm to be able to use the fill() for this purpose, as indicated by Bjarne's example, won't I need to use a reference '[&count]' inside the lambda capture clause to be able to reassign the original indices element value with the incrementing count var via the 'return ++count;' lambda statement block?
I admit I don't quite understand all about these lambdas just yet! :)
Bjarne's example doesn't compile. It can't compile, not unless they defined std::fill differently in C++0x. Maybe it was from a conceptized version of std::fill that could take a function, but the actual version of it (according to section 25.1 of N3242) takes an object, not a function. It copies that object into every element of the list. Which is what that one is trying to do.
The function you're looking for is std::generate.
Try this:
for_each(indices.begin(), indices.end(), [&count](int& it)
{
it = ++count;
});
it is currently iterated content of vector, and is coming via reference.
I hope it's OK to add an "update" style answer, for the benefit of any future readers who may have this same question. Please let me know since I'm new here.
So, here's my final reworked form of the code that does what I'm wanting:
#include <iostream>
#include <vector>
#include <algorithm>
//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
int index{ base };
std::generate(ints.begin(), ints.end(), [&index]() {
return index++; //post-incr.
});
}
//Default wrapper to overwrite a vector<int>
// with incrementing values, base-0.
void init_integers(std::vector<int>& ints) {
init_integers(ints, 0);
}
//Test lambda-based vector<int> initialization.
int main() {
std::vector<int> indices( 50 );
init_integers(indices);
//test output loaded indices.
for (auto x : indices) {
std::cout << x << std::endl;
}
}
Thanks for the helpful answers, I find this a much easier approach. I'll very likely be using lambdas from now on for algorithms that take a function object!
Update 2:
Based on ildjarn's comment to the original post above:
"Note that the exact functionality here is implemented by a new C++0x algorithm -- std::iota."
After testing, I've modified the appropriate code to:
...
#include <numeric>
//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
std::iota(ints.begin(), ints.end(), base);
}
...
and it's working fine. ("Iota", s26.7.6, of N3242).
The simpler and cleaner (though a bit obscure), the easier to read--and more importantly--maintain.
Thanks ildjarn! (Though it was a good exercise personally to go through this process to pick up some further insight on the C++0x lambdas!) :)
-Bud Alverson
Is there a way to create a vector< mem_fun_t< ReturnType, MyClass > > ?
The error i'm seeing is:
error C2512: 'std::mem_fun1_t<_Result,_Ty,_Arg>' : no appropriate default constructor available
I really can't see why it would not work, but it's actually a pretty ugly solution. Just take vector<function<ReturnType(MyClass*)>> and be without those issues present in C++03 binders.
You certainly can create such a vector.
#include <vector>
#include <functional>
#include <iostream>
struct MyClass
{
int a() { return 1; }
int b() { return 2; }
};
int main()
{
std::vector<std::mem_fun_t<int, MyClass> > vec;
vec.push_back(std::mem_fun(&MyClass::a));
vec.push_back(std::mem_fun(&MyClass::b));
MyClass x;
for (size_t i = 0; i != vec.size(); ++i) {
std::cout << vec[i](&x) << '\n';
}
}
If you are having problems, read the error message carefully. For example, std::mem_fun can return all sorts of wrappers, depending on what you pass to it.
Or indeed, switch to boost's or C++0x's function.
Edit: With this particular error message, I assume that you are doing something that invokes the default constructor for contained type (e.g resize or specifying the size with the vector's constructor). You can't use those functions.
mem_fun_t meets the requirements to be stored in a container (it is copy-constructible and assignable), so the answer is yes.
However, it isn't default-constructible or comparable, so there are some things you can't do with a container of them, including:
Resizing, unless you provide a value to fill with
Constructing with a non-zero size, unless you provide a value to fill with
Comparing containers
The error you are seeing comes from trying to either resize, or construct with a size.