I have a simple usage of traversing a temporary std::valarray expression in range for loop, but got error: invalid range expression ...
main.cpp
#include <iostream>
#include <valarray>
int main()
{
std::valarray<int> xxx {2,7,1,8,2,8};
std::valarray<int> zzz {xxx};
for (auto x : xxx + zzz) std::cout << x << std::endl;
return 0;
}
clang++ main.cpp -std=c++11
main.cpp:10:17: error: invalid range expression of type 'std::__1::__val_expr<std::__1::_BinaryOp<std::__1::plus<int>, std::__1::valarray<int>, std::__1::valarray<int> > >'; no viable 'begin' function available
for (auto x : xxx + zzz) std::cout << x << std::endl;
^ ~~~
Is there really a good reason that it does not compile as I expected?
Return type of the overloaded operator+ is valarray<T>, so theoretically, value of the expression should be a temporary instance of type valarray<T>.
Synopsis:
template<class T> valarray<T> operator+ (const valarray<T>& x, const valarray<T>& y);
Version: Apple LLVM version 8.0.0 (clang-800.0.38) Target: x86_64-apple-darwin15.6.0
Note following line works
for (auto x : xxx += zzz) std::cout << x << std::end;
As a "begin" and "end" are available for the operator+ return type, namely valarray<T> I'd say the error is wrong and it should compile.
What do you want to do?
If you want to traverse xxx do the for only in it:
for (const auto x : xxx) std::cout << x << std::endl;
But answering the basics of your question, the expression (xxx + yyy) is not iterable. If you want to do the for loop in both, you do two fors:
for (auto x : xxx) std::cout << x << std::endl;
for (auto x : zzz) std::cout << x << std::endl;
If you want to do it in a single loop, you can append both
xxx += yyy;
for (auto x : xxx) std::cout << x << std::endl;
PD from edit: The line
for (auto x : xxx += yyy) std::cout << x << std::endl;
works because it makes the append first and then iterates. Is equivalent to my last suggestion. But (xxx+yyy) is not iterable.
From your comment:
valrray::operator+(valarray) does not exist.
valrray::operator+=(valarray) does exist.
The range for loop uses the non-member std::begin and std::end, which are not required to exist for the return type of operator+ for std::valarray.
The portable syntax is
for(auto x : std::valarray<int>(xxx + zzz))
This is noted on cppreference and in the standard under 26.7.1[valarray.syn]p4.1
This is a really good question. The reason is the behavior of A+B over valarrays.
Let us see what I mean by this.
First, try these lines.
std::valarray<int> xxx {2,7,1,8,2,8};
std::valarray<int> zzz {xxx};
auto t=xxx+zzz;
cout<<typeid(t).name()<<endl;
cout<<typeid(xxx).name()<<endl;
cout<<typeid(xxx+zzz).name()<<endl;
you will notice that they are not the same, and this is due to the definition of the + operator here https://en.cppreference.com/w/cpp/numeric/valarray/operator_arith3
As it is written the type is deduced. This means that its behavior is similar to auto. The question then is why does it not deduce the same type, valarray. Probably, it is due to a compiler optimization feature, or maybe it is a mistake, but it is clear that the reference does not force the compiler to deduce the same type. The thing is the deduced type happens to be not iterable by a range based for loop.
Please let me know if anything is not clear.
Related
I'm using a set of objects in C++ to get log(n) times for inserting and finding.
In the code below I'm able to insert elements and make them ordered by x attribute, however, I'm not able to use lower_bound to find the lower bounds based on the same attribute. I don't know how to fix that. Any help will be appreciated.
Most of the examples on sets that I could find were not about a set of objects
struct MyObject {
float x = 0;
float y = 0;
const bool operator < ( const MyObject &r ) const{
return ( x< r.x);
}
};
set<MyObject> nset;
int main(){
MyObject n1;
n1.x=5;
n1.y=1;
MyObject n2;
n2.x=3;
n2.y=2;
nset.insert(n1);
nset.insert(n2);
// this works, the elementes are sorted according to x
for(auto elem: nset){
cout << elem.x << endl;
}
// this doesn't work
set<MyObject>::iterator it = lower_bound(nset.begin(), nset.end(), 1.2);
cout << it->x << endl;
//neither this one
// set<MyObject>::iterator it = nset.lower_bound(1.2);
// cout << it->x << endl;
cout << "hello" << endl;
return 0;
}
I want the lower bound function to point me to the lower bound "x" in the set of objects but the code fails to compile. Compiler error to the first lower bound says: Invalid operands to binary expression ('const MyObject' and 'double')
Compiler error to the second lower bound says: No matching member function for call to 'lower_bound'
EDIT: while the answer provided by user: 1201ProgramAlarm was quite helpful for me to understand and fix the error. I still think it is more convenient in my case to have a lower_bound function that accepts floats rather than objects. So I have implemented the following function to help me achieve that. Copied below just in case others were interested:
set<MyObject>::iterator mylower_bound(set<MyObject> &myset, float val){
MyObject f;
f.x = val;
set<MyObject>::iterator it = myset.lower_bound(f);
return it;
}
nset stores MyObject objects, and lower_bound needs one of the thing stored in the set. You're passing it 1.2, which is a double, but there is no way to construct a MyObject from a double. Thus the compilation failure.
You'll need to pass a MyObject to nset.lower_bound to do your search.
I have following code example. I am passing the pointer to a function. When I pass the pointer to the function it seems the function initializes the argument to some random number. But, when I pass the address of the variable to the function it gives expected result.
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vector
class A
{
public:
A(int i) { num = i; }
bool IsPresent (A& a) {
std::cout << "Comparing " << num << " vs " << a.num << '\n';
return (num == a.num);
};
int num;
};
int main () {
std::vector<A*> myvector;
A a1(10);
A a2(20);
A a3(30);
A a4(40);
A a(40);
const A *pa = &a;
std::cout << "pa is " << pa << '\n';
myvector.push_back(&a1);
myvector.push_back(&a2);
myvector.push_back(&a3);
myvector.push_back(&a4);
std::vector<A*>::iterator it = std::find_if (myvector.begin(), myvector.end(),
std::bind2nd(std::mem_fun(&A::IsPresent), pa));
if (it != myvector.end())
std::cout << "The first equal value is " << (*it)->num << '\n';
else
std::cout << "Cannot find a match";
return 0;
}
Why the function bool IsPresent (A& a) initializes the variable (A& a) to random value when the parameter is passed by pointer and works when I pass reference of it?
When passed as pointer the result is
pa is 0x7b10b4d52e80
Comparing 10 vs -1261097344
Comparing 20 vs -1261097344
Comparing 30 vs -1261097344
Comparing 40 vs -1261097344
Cannot find a match
When Passed as reference:
pa is 0x75002e9dbb30
Comparing 10 vs 40
Comparing 20 vs 40
Comparing 30 vs 40
Comparing 40 vs 40
The first equal value is 40
And why the code compiles in first place? The function I am calling expects a reference and I am passing a pointer. Shouldn't the compiler give a warning/error as function not found?
std::bind2nd is really poorly designed.
template< class F, class T >
std::binder2nd<F> bind2nd( const F& f, const T& x )
evaluates to:
std::binder2nd<F>(f, typename F::second_argument_type(x))
and yes, that is a C-style cast.
We end up with doing an (A&)(pa), which becomes reinterpret_cast<A&>(pa).
Which reinterprets the memory of the pointer to A as an instance of A.
Did I say that bind2nd was poorly designed? I meant it.
C++11 brings lambdas and std::bind, both of which are head and shoulders and body and feet and foundation and planet above bind2nd and bind1st.
There is a reason why std::bind2nd is deprecated and removed from the standard. This is only part of the reason (also because it relies on its function arguments telling it what the argument types are, which std::bind does not).
std::mem_fun is also deprecated and removed from the standard, but it does nothing wrong here. Still, replace it with std::mem_fn which does the same job but better as a first step.
Your code will fail to compile if you blindly replace std::mem_fun with std::mem_fn and std::bind2nd with std::bind( first_arg, std::_1, second_arg ) unless second_arg matches the right type. It will do so in a spew of template spam.
Better is:
std::vector<A*>::iterator it = std::find_if (
myvector.begin(), myvector.end(),
[pa](A* a){ a->IsPresent(*pa); }
);
which if you forget to dereference pa generates a really simple and easy to read compiler error message.
Why the function bool IsPresent (A& a) initializes the variable (A& a) to random value when the parameter is passed by pointer and works when I pass reference of it?
The "A& a" parameter is defined as a reference variable, when you pass the pointer object, it is trying to interpret the object as a reference. The correct way is pass its content.
In order to improve your solution, you can define isPresent as bool isPresent(const A& a)
And why the code compiles in first place? The function I am calling expects a reference and I am passing a pointer. Shouldn't the compiler give a warning/error as function not found?
It can be interpreted wrongly as a reference. As a result it compile correctly but the execution fails.
New to boost::hana and trying a simple experiment to find a type in a set of types and just print its typeid.name. However I am getting static_assert errors (NOTE: Xcode 7.2.1)
This is the code:
auto set = hana::make_set(hana::type_c<int>, hana::type_c<float>);
auto s = hana::adjust( set, hana::type_c<int>, [](auto x){ std::cout << typeid(x).name() << std::endl; });
The error is:
"hana::adjust(xs, value, f) requires 'xs' to be a Functor");
However this seems at odds with the documentation for adjust which states that xs needs to be a structure.
Any advice appreciated as I assume I'm missing something fundamental in my understanding.
The problem is that Hana uses functional programming terminology, where Functor means something different from what it typically is used to mean in C++ (i.e. a function object).
In the signature for adjust:
(auto&& xs, auto&& value, auto&& f)
adjust: F(T) × U × (T → T) → F(T)
then xs is F(T), a Functor over T; f is (T → T), a function object that maps values of T to T.
The other problem here is that lowercase and uppercase F refer to different objects within the signature.
Set is not a Functor, because of its invariant that values occur at most once. If you replace make_set with make_tuple (and ensure that your f returns a value), your code will compile (Example):
auto t = hana::make_tuple(hana::type_c<int>, hana::type_c<float>);
hana::adjust(t, hana::type_c<int>, [](auto x){ std::cout << typeid(x).name() << std::endl; return x; });
However, you should probably not be using hana::adjust here, as you don't care about the return value; instead, use hana::filter with hana::for_each (Example):
auto s = hana::make_set(hana::type_c<int>, hana::type_c<float>);
hana::for_each(hana::filter(hana::to_tuple(s), hana::equal.to(hana::type_c<int>)),
[](auto x){ std::cout << typeid(x).name() << std::endl; });
Somehow inspired by the expression template code in Expression templates and C++11, written by Paul Preney, I decided to test the following:
template<typename T>
struct X
{
X(T t) : t(std::forward<T>(t)) {}
T t;
};
template<typename T>
auto CreateX(T&& t) -> X<decltype(std::forward<T>(t))>
{
return X<decltype(std::forward<T>(t))>(std::forward<T>(t));
}
Then, I used it to produce an instance of X<const vector<int>&> and X<vector<int>&&> as follows:
int main()
{
int vec = {1,2,3,4};
auto x1 = CreateX(vec);
auto x2 = CreateX(vector<int>{5,6,7,8});
cout << "x1: "; for(auto x : x1.t) cout << x << " "; cout << endl;
cout << "x2: "; for(auto x : x2.t) cout << x << " "; cout << endl;
}
The output is:
x1: 1 2 3 4
x2: 0 0 33 0 0 0 7 8
which shows that the life-time of the temporary vector<int>{5,6,7,8} is not being extended, and the rvalue-reference member X::t binds to something else.
Okay, from this answer What is the lifetime of the class data member which const reference to a rvalue?, I know this is the expected behaviour.
However, the question here is: what is different in Paul Preney' code in Expression templates and C++11 that permits the temporary vectors to exist as long as the rvalue-references members exist? See his Case 2, where temporaries are created.
Apparently, the same construct there is used here, but I am probably missing something.
Edit:
Based on the answer of R. Martinho Fernandes below, I tried the following:
int main()
{
using namespace std;
auto expr = math_vector<3>{1.0, 1.1, 1.2} + math_vector<3>{2.0, 2.1, 2.2};
cout << "vec1: "; for(int i = 0; i < 3; ++i) cout << expr.le()[i] << " "; cout << endl;
cout << "vec2: "; for(int i = 0; i < 3; ++i) cout << expr.re()[i] << " "; cout << endl;
}
and it turns out that this is a valid code that outputs:
vec1: 1.0 1.1 1.2
vec2: 2.0 2.1 2.2
Therefore, apparently references stored in the expression template is not dangling. What is going on here?
what is different in Paul Preney' code in Expression templates and C++11 that permits the temporary vectors to exist as long as the rvalue-references members exist?
Nothing permits such a thing.
The temporary vectors there exist until the end of the full expression, as any other temporary that isn't bound to a local reference variable. That is enough in Paul's code because the code immediately materialises the expression tree into an actual math_vector, and the temporaries are not needed anymore after that.
Paul's code does not store any expression template node (math_vector_expr) anywhere, while your code stores one (X) as x2. That's a known issue with auto: it does the wrong thing when you are using expression templates because it results in storing the expression tree, which is likely to contain references that will become dangling right away.
In order to make it totally clear, the following is fine.
math_vector<3> result =
math_vector<3>{1.0, 1.1, 1.2} +
math_vector<3>{2.0, 2.1, 2.2} +
math_vector<3>{3.0, 3.1, 3.2} +
math_vector<3>{4.0, 4.1, 4.2}
; // no references are held to any temporaries past this point
The following is not fine.
math_vector_expr<3> result = // or auto
math_vector<3>{1.0, 1.1, 1.2} +
math_vector<3>{2.0, 2.1, 2.2} +
math_vector<3>{3.0, 3.1, 3.2} +
math_vector<3>{4.0, 4.1, 4.2}
; // result now holds references to those temporaries
The problem - as R. Martinho Fernandes states in his answer - is that you capture references to rvalues in your "expression tree" which outlive their referents. The solution is to only store references to lvalues, and to capture objects passed by rvalue reference directly. In other words, store their values in the expression tree instead of by reference (Live code at Coliru):
template<typename T>
struct X
{
X(T t) : t(std::move(t)) {}
T t;
};
// Capture lvalue references
template<typename T>
X<const T&> CreateX(const T& t)
{
return X<const T&>(t);
}
// Copy rvalue references
template<typename T>
typename std::enable_if<std::is_rvalue_reference<T&&>::value,X<T>>::type
CreateX(T&& t)
{
return X<T>(std::move(t));
}
If the user passes you an lvalue reference, it is her responsibility to ensure that the referent outlives the expression tree object.
This question already has answers here:
How to use range-based for() loop with std::map?
(5 answers)
Closed 9 years ago.
The new range-based for loops really improve readability and are really easy to use. However, consider the following :
map<Foo,Bar> FooAndAssociatedBars;
for (auto& FooAndAssociatedBar : FooAndAssociatedBars) {
FooAndAssociatedBar.first.doSth();
FooAndAssociatedBar.second.doSomeOtherThing();
}
It may be a detail but I find it would have been more readable if I could have done something like :
for ( (auto& foo, auto& bar) : FooAndAssociatedBars) {
foo.doSth();
bar.doSomeOtherThing();
}
Do you know an equivalent syntax ?
EDIT:
Good news: C++17 has a proposal that adresses this problem, called structured bindings (see 1). In C++17, you should be able to write:
tuple<T1,T2,T3> f(/*...*/) {
/*...*/
return {a,b,c};
}
auto [x,y,z] = f(); // x has type T1, y has type T2, z has type T3
which solves this readability problem
There is no such thing as you want. The closest is to declare variables inside the loop:
for (auto& FooAndAssociatedBar : FooAndAssociatedBars) {
auto& foo = FooAndAssociatedBar.first;
auto& bar = FooAndAssociatedBar.second;
// ...
}
Not a good idea. Sooner or later, you would want the same for a std::tuple, and compiler should be able to use std::get<> on the tuple automatically. In my opinion your approach is pleasing you at the moment only, and you would find problems with this approach (assume it is implemented that way).
Standard committee has designed range-based for-loop with deep consideration. It is way better than foreach loop in other languages, and it is way shorter. Couple it with auto& and you are done!
And of course, you always have the possibility to use lambdas.
std::map<int, const char*> m { { 4, "hello" }, { 11, "c++" } };
convenient_for_each(m, [](int a, const char* b) {
std::cout << b << a << std::endl;
});
convenient_for_each(m, [](std::pair<int, const char> p) {
std::cout << p.first << p.second << std::endl;
});
Or wrapped as macro (not recommended)
FOREACH((int a, const char* b), m, std::cout << a << b << std::endl);
FOREACH((std::pair<int, const char*> p), m, std::cout << p.first << p.second << std::endl);
(Hackish sample implementation at LWS)
Auto won't work though, I'm still waiting for polymorphic lambdas. My approach is theoretically able to handle tuples as well.