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.
Related
I'm using the ranges library to help filer data in my classes, like this:
class MyClass
{
public:
MyClass(std::vector<int> v) : vec(v) {}
std::vector<int> getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
return std::vector<int>(evens.begin(), evens.end());
}
private:
std::vector<int> vec;
};
In this case, a new vector is constructed in the getEvents() function. To save on this overhead, I'm wondering if it is possible / advisable to return the range directly from the function?
class MyClass
{
public:
using RangeReturnType = ???;
MyClass(std::vector<int> v) : vec(v) {}
RangeReturnType getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
// ...
return evens;
}
private:
std::vector<int> vec;
};
If it is possible, are there any lifetime considerations that I need to take into account?
I am also interested to know if it is possible / advisable to pass a range in as an argument, or to store it as a member variable. Or is the ranges library more intended for use within the scope of a single function?
This was asked in op's comment section, but I think I will respond it in the answer section:
The Ranges library seems promising, but I'm a little apprehensive about this returning auto.
Remember that even with the addition of auto, C++ is a strongly typed language. In your case, since you are returning evens, then the return type will be the same type of evens. (technically it will be the value type of evens, but evens was a value type anyways)
In fact, you probably really don't want to type out the return type manually: std::ranges::filter_view<std::ranges::ref_view<const std::vector<int>>, MyClass::getEvens() const::<decltype([](int i) {return ! (i % 2);})>> (141 characters)
As mentioned by #Caleth in the comment, in fact, this wouldn't work either as evens was a lambda defined inside the function, and the type of two different lambdas will be different even if they were basically the same, so there's literally no way of getting the full return type here.
While there might be debates on whether to use auto or not in different cases, but I believe most people would just use auto here. Plus your evens was declared with auto too, typing the type out would just make it less readable here.
So what are my options if I want to access a subset (for instance even numbers)? Are there any other approaches I should be considering, with or without the Ranges library?
Depends on how you would access the returned data and the type of the data, you might consider returning std::vector<T*>.
views are really supposed to be viewed from start to end. While you could use views::drop and views::take to limit to a single element, it doesn't provide a subscript operator (yet).
There will also be computational differences. vector need to be computed beforehand, where views are computed while iterating. So when you do:
for(auto i : myObject.getEven())
{
std::cout << i;
}
Under the hood, it is basically doing:
for(auto i : myObject.vec)
{
if(!(i % 2)) std::cout << i;
}
Depends on the amount of data, and the complexity of computations, views might be a lot faster, or about the same as the vector method. Plus you can easily apply multiple filters on the same range without iterating through the data multiple times.
In the end, you can always store the view in a vector:
std::vector<int> vec2(evens.begin(), evens.end());
So my suggestions is, if you have the ranges library, then you should use it.
If not, then vector<T>, vector<T*>, vector<index> depending on the size and copiability of T.
There's no restrictions on the usage of components of the STL in the standard. Of course, there are best practices (eg, string_view instead of string const &).
In this case, I can foresee no problems with handling the view return type directly. That said, the best practices are yet to be decided on since the standard is so new and no compiler has a complete implementation yet.
You're fine to go with the following, in my opinion:
class MyClass
{
public:
MyClass(std::vector<int> v) : vec(std::move(v)) {}
auto getEvens() const
{
return vec | ranges::views::filter([](int i) { return ! (i % 2); });
}
private:
std::vector<int> vec;
};
As you can see here, a range is just something on which you can call begin and end. Nothing more than that.
For instance, you can use the result of begin(range), which is an iterator, to traverse the range, using the ++ operator to advance it.
In general, looking back at the concept I linked above, you can use a range whenever the conext code only requires to be able to call begin and end on it.
Whether this is advisable or enough depends on what you need to do with it. Clearly, if your intention is to pass evens to a function which expects a std::vector (for instance it's a function you cannot change, and it calls .push_back on the entity we are talking about), you clearly have to make a std::vector out of filter's output, which I'd do via
auto evens = vec | ranges::views::filter(whatever) | ranges::to_vector;
but if all the function which you pass evens to does is to loop on it, then
return vec | ranges::views::filter(whatever);
is just fine.
As regards life time considerations, a view is to a range of values what a pointer is to the pointed-to entity: if the latter is destroied, the former will be dangling, and making improper use of it will be undefined behavior. This is an erroneous program:
#include <iostream>
#include <range/v3/view/filter.hpp>
#include <string>
using namespace ranges;
using namespace ranges::views;
auto f() {
// a local vector here
std::vector<std::string> vec{"zero","one","two","three","four","five"};
// return a view on the local vecotor
return vec | filter([](auto){ return true; });
} // vec is gone ---> the view returned is dangling
int main()
{
// the following throws std::bad_alloc for me
for (auto i : f()) {
std::cout << i << std::endl;
}
}
You can use ranges::any_view as a type erasure mechanism for any range or combination of ranges.
ranges::any_view<int> getEvens() const
{
return vec | ranges::views::filter([](int i) { return ! (i % 2); });
}
I cannot see any equivalent of this in the STL ranges library; please edit the answer if you can.
EDIT: The problem with ranges::any_view is that it is very slow and inefficient. See https://github.com/ericniebler/range-v3/issues/714.
It is desirable to declare a function returning a range in a header and define it in a cpp file
for compilation firewalls (compilation speed)
stop the language server from going crazy
for better factoring of the code
However, there are complications that make it not advisable:
How to get type of a view?
If defining it in a header is fine, use auto
If performance is not a issue, I would recommend ranges::any_view
Otherwise I'd say it is not advisable.
I'm trying to find a good solution for the following problem:
I want to implement a function that takes a variable number of container arguments and returns the size of the biggest container. Here is an example:
std::vector<std::string> vStr(2, "foo");
std::vector<int> vInt(1, 123);
std::vector<double> vDouble(3, 1.1);
std::list<char> lChar(4, '*');
// or even more container
size_t uiMaxSize = getMaxContainerSize(vStr, vInt, vDouble, lChar /*, ...*/);
in this case getMaxContainerSize should return 4, because lChar has the biggest size of 4.
I've already implemented this workaround using cstdarg:
#include <cstdarg>
...
size_t getMaxContainerSize(int iCnt, ... )
{
size_t uiMaxSize = 0;
va_list ap;
va_start(ap, iCnt);
for(int i=0; i<iCnt; i++)
{
size_t uiTempSize = va_arg(ap, size_t);
uiMaxSize = uiMaxSize<uiTempSize ? uiTempSize : uiMaxSize;
}
va_end(ap);
return uiMaxSize;
}
...
size_t uiMaxSize = getMaxContainerSize( 4, vStr.size(), vInt.size(), vDouble.size(), lChar.size());
But with this I have to type .size() for every container and I also have to specify the number of containers. I also don't like to use C stuff in C++ programs and I'm asking myself if there is a better way to implement this. Maybe by using some class and overloading operator<<() so I can type something like this:
MaxSizeFinder cFinder;
cFinder << vStr << vInt << vDouble << lChar;
size_t uiMaxSize = cFinder.getResult();
Do you think something like this is possible? Any suggestions?
Thank you.
Use a variadic template:
template<typename... Conts>
std::ptrdiff_t getMaxContainerSize(const Conts&... conts) {
return std::max({conts.size()...});
}
When you pass containers as arguments, the compiler will deduce a list of types for Conts. Each parameter of the function will be a const <deduced type> &*. Using conts.size()... expands to conts1.size(), conts2.size(), ..., contsN.size(), where conts# is each argument given to the function. It turns out std::max has a handy overload that you can delegate this to.
There are a couple key advantages of variadic templates over C variadic functions:
They are type safe - the compiler is guaranteed to complain when types don't match, and you don't need a format string or anything.
The function knows how many arguments were passed, and you can get it with sizeof...(Conts).
Nothing special happens to the arguments when going in. In a variadic function, char would be an int by the time the function has to pick it out, among others.
You don't need to explicitly specify any of the types when you use the arguments. This means you can accept an infinite number of types instead of a predefined list (think printf's format specifiers).
Finally, per the comments, the return type was changed to a signed type that mostly acts as the signed counterpart to size_t (sort of like the non-standard ssize_t).
To future-proof the answer, there will soon be a std::size for a more generic way to get a container's size:
using std::size;
return std::max({size(conts)...});
This expands similar to above: size(conts1), size(conts2), ..., size(contsN)
*Normally, parameter packs are used with T&&... with std::forward instead of const T&.... This would potentially buy you something with third-party classes that have a more efficient size function when the object used is an rvalue. However, it adds complexity in general for a low chance at any benefit.
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.
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.