GC error: taking address of temporary

I have following function:

1
2
3
4
template <> void inline writevalue<boost::gregorian::date> (std::ostream& stream, const boost::gregorian::date& value)
{
 stream.write ((const char*)&(value.year()), sizeof(int));
}

which produces the error in GC "taking address of temporary". VS2010 passes it through.

I understand why GC complains; it is because of the value.year() return value being a temporary object. On the other hand I would like not to introduce a temp. variable,like int temp = value.year(); and then write it into the stream.

My question is: is it possible to satisfy GC in this case without temp. variable?

Thanks.

Why do you not want to use a temp variable?'

By the way. value.year() doesn't return an int, does it?
I wouldn't have expected it to work on VC++ either.

I don't have boost installed on this system, but the following nonsensical example fails when I try to compile it with VS2010.
error C2102: '&' requires l-value


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct date
{
	int _year ;
	int year() const { return _year ; }
};

void inline writevalue(std::ostream& stream, const date& value)
{
 stream.write ((const char*)&(value.year()), sizeof(int));
}

int main()
{
	writevalue(std::cout, date()) ;
}

Last edited on
Peter87:
as far as I can tell from looking into the source of datetime boost library the return value of year() is uint32. My example was adapted from the production code, so I changed sizeof(uint32) to sizeof(int).

The reason of not using temp var in this case is not to pollute the code with statements that I can avoid. Works on VS2010 without templib :).

cire:
No, my example does not fail on VC, it happily compiles as part of a much larger project. I have whole bunch of these writevalue functions.

If you dig around http://www.boost.org/doc/libs/1_47_0/boost/date_time/gregorian/, you find value.year() returns a utility object of type greg_year which has an overloaded unsigned short operator(). You're taking the address of that object, which is probably not what you wanted to do.

If I were you, I'd thank GCC for flagging my erroneous code and go about fixing it.
cire,

Thank you for your reply, it is very helpful. A side note - the reason I post my questions here is to fix the errors that are not that obvious to me. And to thank anyone, who, just like you, is kind enough to spend his/her time answering my questions. As soon as I understand what the error is I am immediately going after fixing it. Otherwise there is no point.

I disagree with your conclusion. The compiler takes the address of what operator() of greg_year returns (which is indeed short and not uint32 as I posted. I looked into the wrong template param). I think that is why the code works in windows for a # of years in production.

I disagree with your conclusion. The compiler takes the address of what operator() of greg_year returns (which is indeed short and not uint32 as I posted. I looked into the wrong template param). I think that is why the code works in windows for a # of years in production.


Your code does not (implicitly or explicitly) invoke the operator, hence you are not taking the address of what operator short() returns. Your code works because greg_year is a trivial type and the address of the data coincides with the address of the object. It's quite possible it would stop working inexplicably at some point because the implementation of greg_year changed.
Last edited on
cire:

I agree that this code will stop working even in Windows after: implementation of greg_year changes or new compiler is released.

Your code works because greg_year is a trivial type and the address of the data coincides with the address of the object


This issue can be an interesting (for me at least) discussion. I have to disagree again - greg_year is absolutely not a trivial type.
1
2
3
4
5
class greg_year : public greg_year_rep {
  public:
    greg_year(unsigned short year) : greg_year_rep(year) {}
    operator unsigned short()  const {return value_;}
  };



and greg_year_rep is

typedef CV::constrained_value<greg_year_policies> greg_year_rep;

Thank you for your replies.
I will appreciate it if you can continue to prove your point that greg_year is a trivial type.


You can replace "trivial" with "standard layout." I have not yet (nor do I plan to) dig far enough into the documentation to determine definitively whether this is the case or not. The fact your code works (for you) is enough to satisfy my curiosity on the subject.

What you're disagreeing with (my choice of terminology) has no bearing on the issue.
Last edited on
cire,

From the discussion of "trivial" and "standard" layouts in c++11 <a href="http://en.wikipedia.org/wiki/C%2B%2B11">wiki</a> it is clear that greg_year is neither "trivial" or "standard".

My code definitely has an error which was correctly caught by GC. Thank you for pointing some finer points to me.
it is clear that greg_year is neither "trivial" or "standard".


From the information presented here and the limited information presented on the boost site, all that is clear to me is that it is possible greg_year is a standard layout type, but I'm done here. =)

Topic archived. No new replies allowed.