-4

I have kind of a weird issue and while trying to create a small example to post here on stackoverflow, I failed to reproduce. Hopefully, this will still ring a bell to somebody, or somebody has a good idea to dig further...

On my Mac, the below code compiles fine with gcc 4.9.2. I'm using g++ -std=c++11 test.cpp. On some other Linux/Fedora machine with gcc 4.7.2, I get a compilation error. Not on the below test example, but on a more complicated problem. I'm, however, not allowed to post that here, and unable to see what exactly is different.

I did, however, find a way to make it compile, by simply trying lots of things. I hope somebody might see what is wrong from that hint. The way I could get my program to compile was to change the lambda body from v.push_back... into this->v.push_back...

Any idea why that could be??

The compilation error I'm seeing is:

/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: no known conversion for implicit 'this' parameter from 'const std::vector<aggregate>*' to 'std::vector<aggregate>*'
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: no known conversion for argument 1 from 'aggregate' to 'std::vector<aggregate>::value_type&& {aka aggregate&&}'

The following fails to compile on the Linux machine with gcc 4.7.2:

#include <vector>
#include <iostream>
#include <functional>

struct aggregate {
    int foo;
    char bar[2];
};

template<typename T>
class test {
private:
    std::vector<aggregate> v;
    std::function<void(aggregate&)> lambda;
public:
    test() :
        lambda([this] (aggregate& a) { v.push_back(a); })
    {
        v.reserve(8);
    }

    void execute() {
        aggregate a{1, "x"};
        lambda(a);
    }
};

int main() {
    test<int> t;
    t.execute();
}

$ g++ -std=c++11 test.cpp test.cpp
In lambda function:
test.cpp:17:53: error: no matching function for call to 'std::vector<aggregate>::push_back(aggregate&) const'
test.cpp:17:53: note: candidates are:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/vector:65:0, from test.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:881:7: note: no known conversion for implicit 'this' parameter from 'const std::vector<aggregate>*' to 'std::vector<aggregate>*'
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = aggregate; _Alloc = std::allocator<aggregate>; std::vector<_Tp, _Alloc>::value_type = aggregate] <near match>
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:899:7: note: no known conversion for argument 1 from 'aggregate' to 'std::vector<aggregate>::value_type&& {aka aggregate&&}'

But works fine after changing v.push_back... into this->v.push_back...

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
jeebee
  • 63
  • 1
  • 6
  • 1
    [Works fine with a newer GCC](http://coliru.stacked-crooked.com/a/4453e743f0912a40), why are you still using 4.7? – ildjarn Feb 11 '15 at 17:31
  • 3
    Not sure what to say other than "gcc 4.7 has limited C++11 support"? – Yakk - Adam Nevraumont Feb 11 '15 at 17:33
  • 2
    `Not on the below test example, but on a more complicated problem`: so what's the point of the example? – Andy Prowl Feb 11 '15 at 17:35
  • That's a machine not under my control. On my machine I have 4.9.2 which seems to work fine indeed. Note the example program worked on 4.7.2 as well, I failed to provide a good example, but hoped somebody could figure it out, e.g., from the compile error above. – jeebee Feb 11 '15 at 17:35
  • @AndyProwl it's the closest thing I could come up with. – jeebee Feb 11 '15 at 17:36
  • I up-voted this because knowing /why/ there is a failure is important, even if the solution may be, "upgrade." – Sam Feb 11 '15 at 17:37
  • @jeebee Figure *what* out, exactly? You're saying that a machine not under your control has no compiler with good C++11 support. I'm not sure how we can help. – Drew Dormann Feb 11 '15 at 17:37
  • 2
    Voted to close. Without seeing the code that actually causes the problem, giving answers is hardly possible; the best we can do is to formulate conjectures. – Andy Prowl Feb 11 '15 at 17:39
  • Additionally, this works with GCC 4.7.2 (Debian 4.7.2-5)... – jepio Feb 11 '15 at 17:40
  • @jeebee: Does the original code involve templates? In particular, is `test` a class template? – Andy Prowl Feb 11 '15 at 17:45
  • @AndyProwl: yes, test is a class template. I didn't see why that would be important, but I hope you'll tell me? – jeebee Feb 11 '15 at 17:48
  • @jeebee: My wild guess is that you have an issue with dependent names and 2-phase lookup - although that would not explain why the exact same code compiles on 4.9.2, since 4.7.2 does implement 2-phase look correctly. In the real code, is `v` a data member of some class `test` inherits from, rather than a member of `test` itself? – Andy Prowl Feb 11 '15 at 17:51
  • @AndyProwl: wow, thanks! changing class test to template class test and using something like test indeed reproduces my issue! – jeebee Feb 11 '15 at 17:51
  • @jeebee I can't reproduce this (even with gcc 4.6.3) it works for me. Could you try annotating the lamba as mutable: `[this] (aggregate& a) mutable { ... }`? – jepio Feb 11 '15 at 17:52
  • @jeebee: If you're referring to the example you posted in the question, that change should not be enough to reproduce the problem. – Andy Prowl Feb 11 '15 at 17:57
  • @AndyProwl: well, my updated example above gives the exact compile error shown below it. And making the suggested change makes it compile... Maybe something else is relevant in my environment, not sure about that. – jeebee Feb 11 '15 at 18:01
  • @jepio: Changing the lambda to be mutable also makes it compile without any warnings or errors (without having to insert the this->) – jeebee Feb 11 '15 at 18:03
  • @jeebee: The latest example you posted compiles for me on 4.7.3 as well as on 4.6.4. There's no reason to believe it wouldn't compile on 4.7.2. There's definitely something you are not showing. – Andy Prowl Feb 11 '15 at 18:06
  • In particular, the error message shows that the compiler is expecting to find a `'std::vector::push_back(aggregate&) const` member function, which means you are calling `push_back` on a `const` vector. I assume the vector is `const` because this happens inside a `const` member function, but in your example, that's not the case (it happens in the constructor). – Andy Prowl Feb 11 '15 at 18:07
  • @jeebee So the explanation would be that `v` accessed through a `const test *` (as `this` could be in the lambda) becomes `const` itself and hence can't be converted to `vector`. Changing lambda to mutable removes the `const` from `this` and makes it work. No clue why this depends on gcc version. You really **should** post a working (erroneous) example! There's no excuse for not posting one, especially not *i'm not allowed*. Extract what's important to reproduce and post. – jepio Feb 11 '15 at 18:12
  • @AndyProwl: I promise I'm showing you all the code in the update example above ... there's nothing else ... – jeebee Feb 11 '15 at 18:13
  • @jeebee: As I wrote, I took your example, gave it to GCC 4.6.4 and 4.7.3, and it compiles without problems. It's hard for me to believe GCC 4.7.2 rejects it. The error, in particular, shows you're trying to call `push_back()` on a constant vector. That happens nowhere in the code you posted. – Andy Prowl Feb 11 '15 at 18:16
  • @AndyProwl: This is my compiler: $ g++ --version g++ (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2) Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. – jeebee Feb 11 '15 at 18:19
  • @jeebee: Focus on this: "*The error, in particular, shows you're trying to call `push_back()` on a constant vector. That happens nowhere in the code you posted.*" – Andy Prowl Feb 11 '15 at 18:20
  • @AndyProwl: Yes, that seems to be the missing part :) – jeebee Feb 11 '15 at 18:22
  • @jeebee: Well, how about providing that part then? :P – Andy Prowl Feb 11 '15 at 18:25
  • _"I get a compilation error. Not on the below test example, but on a more complicated problem. I'm, however, not allowed to post that here, and unable to see what exactly is different."_ How would _we_ be able to, then?? – Lightness Races in Orbit Feb 11 '15 at 19:54
  • @LightnessRacesinOrbit: as you could have read further on, later somebody enabled me to construct an example that does yield the compilation error. Now only we need somebody to confirm this gcc (Red Hat 4.7.2-2). I searched a few nice online c++ compile sites, but none of them included my gcc version. – jeebee Feb 11 '15 at 20:09
  • I'm trying to point out a flaw in your logic that hopefully will aid you in posting next time :) – Lightness Races in Orbit Feb 12 '15 at 10:14

2 Answers2

1

Might the above be a manifestation of this bug in GCC 4.7.2?

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54277

Bug 54277 - [4.7/4.8 regression] Template class member referred to with implicit this inside lambda is incorrectly const-qualified

This answer was reached in a comment thread and is being pulled up here for consideration as a possible answer. If nothing else, it's the closest I've found that explains what's going on and why this doesn't occur in the newer compilers.

Sam
  • 2,939
  • 19
  • 17
  • Thanks sam, and also the others for all insights, I did learn something here. There was quite some criticism for posting here without a concrete example, but in the end (thanks to @andyprowl for the template suggestion) I couldn't have figured this out without all of you. – jeebee Feb 15 '15 at 11:46
-3

I'll bet it's the RValue reference to aggregate. Notice it is of type aggregate&& not aggregate& and that is not supported in gcc 4.7.

https://gcc.gnu.org/gcc-4.7/cxx0x_status.html

 note: no known conversion for argument 1 from 
'aggregate' to 'std::vector::value_type&& {aka aggregate&&}'
Sam
  • 2,939
  • 19
  • 17
  • 1
    It's explicit in the error message from the compiler. It's implied by the variable's use in the code as part of the lambda. – Sam Feb 11 '15 at 17:38
  • On the cxx0x status page you link to it says that rvalue references are supported. – jepio Feb 11 '15 at 17:41
  • So educate instead of blind downvoting. – Sam Feb 11 '15 at 17:41
  • Aaah, thanks, that was very helpful. I'm going to try to update the example above. – jeebee Feb 11 '15 at 17:43
  • You may want to consider posting as a different question. The downvote fairies seem to like everything on this post. – Sam Feb 11 '15 at 17:45
  • 1
    There's nothing to elucidate, just read the error... `no known conversion for implicit 'this' parameter from 'const std::vector*' to 'std::vector*'`. Errors following that are irrelevant, and error converting `T` to `T&&` is nonsensical to begin with. – ildjarn Feb 11 '15 at 17:51
  • T&& is not "nonsensical" in a C++11 codebase, though. (For reference: http://en.cppreference.com/w/cpp/language/move_operator). If GCC 4.7 does have weaknesses in Rvalues, that seems a pretty reasonable reading of the error message. If I've missed something, by all means, post. – Sam Feb 11 '15 at 20:30
  • 1
    I didn't say `T&&` was nonsensical, I said getting an error converting a `T` to a `T&&` is nonsensical (when there's another overload taking a `T const&`. – ildjarn Feb 11 '15 at 21:05
  • T was not a const, so a T& const is not applicable. I think we should drop this. – Sam Feb 11 '15 at 23:59
  • `const&` can bind to _any_ non-`volatile` object, rvalue or lvalue, const or non-const. Dropping it is not helpful for readers who may be misled by your incorrect answer. – ildjarn Feb 12 '15 at 21:10
  • https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54277 Against my better judgement, I'm going to continue this. The above bug may be the cause. I do not appreciate that you, @ildjarn, have only contributed by taking shots. I would appreciate a modicum of professionalism and some effort to give answers. – Sam Feb 13 '15 at 06:29
  • Based on our relative reputation scores, I don't know what would you to believe I don't give answers. However _you_ do not take constructive criticism at all, choosing to deflect instead of taking an opportunity to learn – your loss. – ildjarn Feb 13 '15 at 06:39
  • Hmm, thanks @sam, as far as I -- as quite a c++ beginner -- can understand, this seems to explain what I'm seeing. Would you mind posting this as an answer so that I can accept it? – jeebee Feb 13 '15 at 13:51