say I have
struct S {
double A;
double B;
double C;
};
and
std::vector<S> vecS(10);
I am trying to write a generic function void F(std::vector<S> vecS,structure S.x) such that the following computation can happen
F(std::vector<S> vecS, structure S.x) {
for(i=1;i<10;i++)
vecS[0].x += vecS[i].x;
// note the structure does not have memeber "x"
// I want to give that as a generic input to access A,B or C
}
The above code is not correct code, but I am just trying to demonstrate what I am trying to compute.
What I am trying to compute is loop over the vector of structs for a specific element. Is this possible in a simple nice way? Can someone please give me some pointers how to access a member of a structure in a generic way (maybe that is what I need to write this function).
Thanks in advance.
What you need is a pointer to member:
void F( std::vector<S> &vecS, double S::*ptr )
{
for(i=1;i<10;i++)
vecS[0].*ptr += vecS[i].*ptr;
}
// now call for A
F( vec, &S::A );
If you need it to work with different types, not only double as in this case, use template.
PS I did not notice first, but you have to pass vector as reference, as you modifying element in it.
Well, it's not generic in the sense that you have a vector hardcoded, but let's ignore that for a second.
What you want is a pointer-to-member:
template <typename T, typename M>
F(std::vector<S> vecS, M T::* member) {
for(i=1;i<10;i++)
vecS[0].*member += vecS[i].*member;
}
Call as F(vec, &myClass::A)
The concept you are looking for is called a pointer to member. You can't use the exact syntax as you have written, and pointer to member syntax is rather ugly and not commonly used. But here's the basics.
double S::*x = &S::A;
vecS[0]->*x += vecS[i]->*x
See the following for more details:
http://en.cppreference.com/w/cpp/language/operator_member_access#Built-in_pointer-to-member_access_operators
http://en.cppreference.com/w/cpp/language/pointer
Also, unrelated to your question, but you need to declare the type of your loop variable i. Currently, it is undefined.
Related
I have to write a simple code that takes a char as input or a string with an integer. Then makes a std vector, depending on the input. If the text says int I have an int vector.
The only problem is that I don't want to declare for each variable type a vector even if empty, and I want to make it scalable so if someday I want to put a struct or something else in it i can.
dvec::dvec( char t){
if ( t=='i')
vector<int> a;
else if( t=='f')
vector<float> a;
}
If all you want is primitive types or pointers, you can make a union (8 bytes in size) and a vector of that union. It's a bit C'ish, but template is a compile time solution, so for a linkable solution, you need space for every type. You can have getters, setters, constructors for each type.
You can implement this thing in two ways:
1.
using element_type = std::variant<char, int, float /* ... other types */>;
using dvec = std::vector<element_type>;
This will be type safe, albeit the disadvantage is that every element of the vector is a variant, which might not be what you want.
2.
using dvec = std::variant<std::vector<char>,
std::vector<int>,
std::vector<float> /* ... other vector types */>;
This will give you a variant of vectors, where all vector elements are homogeneous.
This cumbersome expression could be simplified by using Boost.Mp11
template<class T> using vectorize_t = std::vector<T>;
template<typename ...T>
using dvec = std::variant<mp_transform<vectorize_t, T...>>;
which basically puts all respective types in T... to an std::vector.
Write a helper function to do the real work.
template <typename T>
void do_work() {
std::vector<T> a;
// do stuff
}
// ...
if(t == 'i') {
do_work<int>();
}
else if(t == 'f') {
do_work<float>();
}
else if(t == 's') {
do_work<your_struct>();
}
Depending on what your specific uses are you might need (or at least want) to have do_work just call multiple functions, that way you can specialize if needed.
I have an array of vectors in one class:
class MeasurementData
{
private:
std::vector<double> m_measuredStrengths[3];
}
And I would like a function of another class to examine that and pass back an integer based on the analysis, e.g.
int CStrengthAnalyser::GetBestFit(std::vector<double> measuredStrengths[3])
{
int bestFit = -1;
// do stuff
return bestFit;
}
And I'm a little confused by the best practice for passing this kind of object around, plus setting up my receiving function to guarantee no changes to the original data.
Is my function declaration OK as-is, or do I need to add some best practice tweaks?
The function you have right now is the same function as:
int CStrengthAnalyser::GetBestFit(std::vector<double> * measuredStrengths )
So it can definitely modify the vectors. If you're always dealing with an array of size 3 you can take a const reference to an array of size 3.
int CStrengthAnalyser::GetBestFit(std::vector<double> const (&measuredStrengths)[3])
Or if you want to make it more generic:
struct CStrengthAnalyser
{
// ...
template<std::size_t N>
int GetBestFit(std::vector<double> const (&measuredStrengths)[N])
{ ... }
};
In this case the member function definition must appear in the header (or, to be precise, the definition must be visible to the compiler at the callsite).
If you want to avoid the ugly reference to array syntax you could change the MeasurementData definition to contain a std::array<std::vector<double>, 3> instead of a plain C array. Then passing a reference to that is cleaner
int CStrengthAnalyser::GetBestFit(std::array<std::vector<double>, 3> const& measuredStrengths)
And finally, you could also deduce the size of the std::array using a function template as shown previously.
I would suggest that you use a vector of vectors here, like
vector<vector<double> > your_measure(3);
When you pass it into another function, you can use the key word const to it, like
my_fun(vector<vector<double> > const & your_vec_vec);
I'm trying to write a function for enumerating through a number of a specific base, where the number is stored in some kind of list. Here is an example, taking a std::vector
void next_value(std::vector<unsigned int> &num, unsigned int base) {
unsigned int carry = 1;
for (unsigned int &n: num) {
n += carry;
if (n >= base) {
carry = 1;
n = 0;
} else {
carry = 0;
}
}
}
The num vector doesn't necessarily need to be a vector, it can be an array, or actually any type that has a std::begin() and std::end() defined for it. Is there a way to express that num can be anything with begin() and end(), but that it must have unsigned int type for its elements?
If you really want to check this, try:
template <class Sequence>
void next_value(Sequence &num, unsigned int base) {
static_assert(boost::is_same<Sequence::value_type, unsigned>::value, "foo");
// ...
If you're not using C++11 yet, use BOOST_STATIC_ASSERT instead.
If you need to support plain C-style arrays, a bit more work is needed.
On the other hand, #IgorTandetnik correctly points out that you probably do not need to explicitly check at all. The compiler will give you an (ugly) error if you pass a type which is truly unusable.
Writing a generic function with a static_assert is a good idea, because you can give the user a helpful error message rather than "foo".
However there is another approach using C++11:
template <typename Container, typename ValueType>
typename std::enable_if<std::is_same<Container::value_type, ValueType>::value, void>::type
next_value(Container& num, ValueType base)
{
// ...
}
This is a rather cryptic approach if you've never seen this before. This uses "Substitution failure is not an error" (SFINAE for short). If the ValueType doesn't match the Container::value_type, this template does not form a valid function definition and is therefore ignored. The compiler behaves as if there is not such function. I.e., the user can't use the function with an invalid combination of Container and ValueType.
Note that I do recommend using the static_assert! If you put a reasonable error message there, the user will thank you a thousand times.
I would not in your case.
Change carry to a book, use ++ instead of +=, make base a type T, and n an auto&.
Finally, return carry.
Your code now ducktypes exactly the requirements.
If you want diagnostics, static assert that the operations make sense with custom error messages.
This let's your code handle unsigned ints, polynomials, bigints, whatever.
I'm currently trying to do a complicated variable correction to a bunch of variables (based on normalizing in various phase spaces) for some data that I'm reading in. Since each correction follows the same process, I was wondering if there would be anyway to do this iteratively rather than handle each variable by itself (since I need to this for about 18-20 variables). Can C++ handle this? I was told by someone to try this in python but I feel like it could be done in C++ in some way... I'm just hitting a wall!
To give you an idea, given something like:
class VariableClass{
public :
//each object of this class represents an event for this particlular data set
//containing the following variables
double x;
double y;
double z;
}
I want to do something along the lines of:
for (int i=0; i < num_variables; i++)
{
for (int j=0; j < num_events; j++)
{
//iterate through events
}
//correct variable here, then move on to next one
}
Thanks in advance for any advice!!!
I'm assuming your member variables will not all have the same type. Otherwise you can just throw them into a container. If you have C++11, one way you could solve this problem is a tuple. With some template metaprogramming you can simulate a loop over all elements of the tuple. The function std::tie will build a tuple with references to all of your members that you can "iterate" like this:
struct DoCorrection
{
template<typename T>
void operator()(T& t) const { /* code goes here */ }
};
for_each(std::tie(x, y, z), DoCorrection());
// see linked SO answer for the detailed code to make this special for_each work.
Then, you can specialize operator() for each member variable type. That will let you do the appropriate math automatically without manually keeping track of the types.
taken from glm (detail vec3.incl)
template <typename T>
GLM_FUNC_QUALIFIER typename tvec3<T>::value_type &
tvec3<T>::operator[]
(
size_type i
)
{
assert(i < this->length());
return (&x)[i];
}
this would translate to your example:
class VariableClass{
public :
//each object of this class represents an event for this particlular data
double x;
double y;
double z;
double & operator[](int i) {
assert(i < 3);
return (&x)[i];
}
}
VariableClass foo();
foo.x = 2.0;
std::cout << foo[0] << std::endl; // => 2.0
Althought i would recomment glm, if it is just about vector math.
Yes, just put all your variables into a container, like std::vector, for example.
http://en.cppreference.com/w/cpp/container/vector
I recommend spending some time reading about all the std classes. There are many containers and many uses.
In general you cannot iterate over members without relying on implementation defined things like padding or reordering of sections with different access qualifiers (literally no compiler does the later - it is allowed though).
However, you can use a the generalization of a record type: a std::tuple. Iterating a tuple isn't straight-forward but you will find plenty of code that does it. The worst here is the loss of named variables, which you can mimic with members.
If you use Boost, you can use Boost.Fusion's helper-macro BOOST_FUSION_ADAPT_STRUCT to turn a struct into a Fusion sequence and then you can use it with Fusion algorithms.
Is there to templatize the "ints" in the lambda function below in the case that there was a standard container of doubles or floats, etc.? I have searched the world over for help with this. I even asked for the help of my professor who says it is possible but is to cryptic about the answer.
template <typename T>
float mean(T &container)
{
auto sum = std::accumulate(container.begin(), container.end(), 0/*initial value*/,
[](int total, int cur)
{
return total+cur;
}//end of lambda
);//end of accumulate
return static_cast<float>(sum) / container.size(); //to find the mean
}//end of mean
Thanks in advance.
There is typically a way to get the type of the contained data from a container.
For e.g you could replace the ints in that function with T::value_type which should support all containers which expose such a typedef.
This wont work for types such as map but you can specialize for it if you want to support them.
But it seems to me that writing such a function that way may induce loss of data
For example
std::vector<float> vf;
vf.push_back(1.3);
vf.push_back(1.5);
vf.push_back(1.3);
vf.push_back(1.123);
vf.push_back(1.526);
float m=mean(vf);
will always return 1
The answer here >>> compute mean using std::accumulate fails in the Edit part is not really true as if I change vf.push_back(1.3); into vf.push_back(3.3); I'll obtain the wished result.