This error has me perplexed.

Started by
31 comments, last by iMalc 11 years ago

Is not the reference valid for the lifetime of the temporary object? I was certain pg.245 of N3337 implies that the temporary object the reference was bound to will exist for the duration of the function, in particular 12.2.5. Am I reading this wrong?

It's kind of a weird part of C++. The reference/object exists, and it will exist for the duration of the function, but it might not really exist... Confusing? A little. There are two types of existance. The "readonly" type of existence, and the "read+write" type of existence. The object exists (in terms of being able to read it) as far as 12.2.5 is concerned. "existence" doesn't mean you can write to an object. It just means it's there.

I suggest reading this. One of the big reasons for this whole thing is to avoid bugs where temporaries are accidentally modified. (think of it, being able to do 2 = 1; would be weird...)

I also suggest reading this. It might not seem like it makes a lot of sense, and in some ways, it doesn't, but it's just one of those things in C++.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
Advertisement

I don't think that's what it means. The idea behind temporaries is that they can be bound to an r-value reference, and that they can be modified. It'd be kinda useless to have a r-value reference to say a string if I couldn't pilfer the data by swapping the internal pointer (which implies both reading and writing to it). If I could only read and not write the pointer then the data would be delete'd right away, which wouldn't really make sense. There's no where I see it stated that temporaries bound to non-const lvalues cannot be modified while temporaries bound to non-const rvalues can be. Also in your example (2 = 1), neither would bind to a non-const lvalue. Also the standard does clearly state the temporary will live till the end of the expression (at the very least), which would include the function call.

Far more baffling though is why isn't the VS2012 compiler linking in the proper template function instantiations, and if I've made a mistake in the compiler or linker settings why didn't it tell me instead of just blowing up...

I don't think that's what it means. The idea behind temporaries is that they can be bound to an r-value reference, and that they can be modified. It'd be kinda useless to have a r-value reference to say a string if I couldn't pilfer the data by swapping the internal pointer (which implies both reading and writing to it). If I could only read and not write the pointer then the data would be delete'd right away, which wouldn't really make sense. There's no where I see it stated that temporaries bound to non-const lvalues cannot be modified while temporaries bound to non-const rvalues can be. Also in your example (2 = 1), neither would bind to a non-const lvalue. Also the standard does clearly state the temporary will live till the end of the expression (at the very least), which would include the function call.

The thing is, you're not supposed to be able to take an l-value reference to an r-value. Yes, there are some ways that an r-value reference may be modified (through calling non-const member functions, or if you're using move semantics), but they're not supposed to be modified through any other means.

But it's possible Visual Studio allows it. I just know that in standard C++, it's illegal.

Far more baffling though is why isn't the VS2012 compiler linking in the proper template function instantiations, and if I've made a mistake in the compiler or linker settings why didn't it tell me instead of just blowing up...

Are you sure that's the error? The error you're describing sounds a whole lot like you're invoking undefined behavior somewhere. Are you linking to two different versions of the standard library? If you're not, then I highly doubt that is your problem, and would expect your problem to be undefined behavior being invoked elsewhere. Seriously though, at least try passing in a variable to throw_detailed() instead of a temporary.

Also, I suggest you post the *full* code, because that's not it. You're not showing what Exception::GetLineNumber() is, for example.

Somewhere you're invoking undefined behavior. I'd be shocked if the template instantiation is the problem (unless you're linking to different versions of the standard library).

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

The function Exception::GetLineNumber() is:


std::string Exception::GetLineNumber () const {
	const int* line = boost::get_error_info<boost::throw_line>(*this);
	if (line) {
		std::stringstream ss;
		ss << *line;
		return ss.str();
		}
	return "unknown line";
	}

BTW I did change throw_detailed to:


template <typename T> BOOST_ATTRIBUTE_NORETURN void ThrowException (T e, const char* func, const char* file, int line) {

and Exception constructor looks like:


Exception::Exception (const std::string& msg) {
	*this << ErrMsgInfo(msg);
	}

And that's all.

Far more baffling though is why isn't the VS2012 compiler linking in the proper template function instantiations, and if I've made a mistake in the compiler or linker settings why didn't it tell me instead of just blowing up...

I have a vague recollection of accomplishing this through haphazard includes spread out unnecessarily. Also, something to do with using different versions of Visual Studio (I've usually had several version installed on the same machine). Sorry about the brain damage here...please post the solution when you find it.

The Four Horsemen of Happiness have left.

The thing is, you're not supposed to be able to take an l-value reference to an r-value. Yes, there are some ways that an r-value reference may be modified (through calling non-const member functions, or if you're using move semantics), but they're not supposed to be modified through any other means.

But it's possible Visual Studio allows it. I just know that in standard C++, it's illegal.


But you bind rvalues to lvalue references all the time. For example:


string s("hello");
cout << s.find(string("l") + string("o")) << endl;

This may be a contrived example, but temporary values are constantly bound to lvalue references.

I found it, a silly oversight on my part (as usual).

I compiled the library with the /vmg compiler option, and I didn't do the same with the program, I had forgotten it.

Thank-you very much for your time and insight. I know I checked my compiler and linker options repeatedly, I'm not sure how I had missed that.

This may be a contrived example, but temporary values are constantly bound to lvalue references.

The rule is that temporaries can't (normally) be bound to non-const lvalue references. Binding a temporary to a const lvalue reference is perfectly fine. Binding a temporary to a non-const lvalue reference can be done, but requires trickery or a compiler extension like MSVC has.

The thing is, you're not supposed to be able to take an l-value reference to an r-value. Yes, there are some ways that an r-value reference may be modified (through calling non-const member functions, or if you're using move semantics), but they're not supposed to be modified through any other means.

But it's possible Visual Studio allows it. I just know that in standard C++, it's illegal.


But you bind rvalues to lvalue references all the time. For example:


string s("hello");
cout << s.find(string("l") + string("o")) << endl;

This may be a contrived example, but temporary values are constantly bound to lvalue references.

Sorry, poor wording on my part. I meant non-const lvalue reference (i.e. the kind of reference we've been talking about in the code).

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

Well even if it wasn't the problem its good to know Corn/SiCrane. Its something I will not do, despite not making much sense IMHO.

This topic is closed to new replies.

Advertisement