error: lvalue required while operator overloading ++/-- etc - c++

I transferred my code to Ubuntu 4.4.1 g++ compiler. While overloading operator ++ (int) as below, it throws error for (T*), but works fine for (T*&). In my earlier version (linux-64, but don't remember exact version) it was working fine with (T*) also.
Any reason, why ?
template<typename T>
struct Wrap
{
void *p; // Actually 'p' comes from a non-template base class
Wrap<T>& operator ++ ()
{
((T*)p) ++; // throws error; if changed to (T*&) then ok!
return *this;
}
// ...
};
int main ()
{
Wrap<int> c;
++c; // calling prefix increment
}

A result of a type-cast is not an lvalue, so it cannot be assigned to and (built-in) ++ is a form of assignment. It was a bug in the compiler if it ever worked.
With reference it compiles (in efect it's the same as *(T**)&p), but due to aliasing rules (compiler may assume that pointers (and references) of different types don't point to the same object) it is formally invalid, though it will work on all known compilers.
The cleanest way it to:
p = static_cast<void *>(static_cast<T *>(p) + 1)
(never use C-style cast in C++) and rely on the compiler being able to compile it exactly the same way as ++. However if you have the template argument available when defining the pointer (in the sample code you do), it's much better to just use properly typed pointer (I'd say it would also work with member pointers, but they don't have meaningful ++).

Looks like you mixing up your prefix and postfix increment signatures. Also, why use a void* if you know your type is T ?
See below for appropriate signatures:
http://www.codeguru.com/forum/showthread.php?t=231051

Related

What is the different between +[](){}; and (+[](){}); and why the expression is valid

As the title stated. The code is compiled using GNU c++2a
int main(){
(+[](){});
return 0;
}
Compiles fine.
However, the following code generates warning: value computed is not used [-Wunused-value]
int main(){
+[](){};
return 0;
}
Further question is: my understanding about the expression [](){} is, it returns an r-value object std::function<void()>. While, I don't know there is a unary operator +, when the + applies on any r-value, should it be a compile error generated? Or maybe because of the operator precedence, the expression is interpreted in another way?
{} is, it returns an r-value object std::function<void()>
No, it creates a lambda/closure which is its own kind of thing. There are cases when that is turned into a std::function, but what you're actually getting is much more similar to a functor (a class that implements operator()) than a std::function - which is a type-erased holder for things which can be called.
The + sign forces the closure to be turned into a function pointer (because that's the only thing thats "easy" to convert to which can have a unary + applied to it), which when wrapped in () "uses" the pointer value in a list context. Without that, you compute a function pointer but then discard it immediately. It's telling you that your + sign is silly.

Is it safe to take the address of a temporary?

In my program, I would like to take the address of a temporary. Here is an example:
#include <iostream>
struct Number {
int value;
Number(int n) {
value = n;
}
};
void print(Number *number) {
std::cout << number->value << std::endl;
}
int main() {
Number example(123);
print(&example);
print(&Number(456)); // Is this safe and reliable?
}
This would output:
123
456
To compile, the -fpermissive flag is requied.
Here is my question: is this safe and reliable? In what possible case could something go wrong?
If your definition of "safe and reliable" includes "will compile and produce the same results if the compiler is updated" then your example is invalid.
Your example is ill-formed in all C++ standards.
This means, even if a compiler can be coerced to accept it now, there is no guarantee that a future update of your compiler will accept it or, if the compiler does accept the code, will produce the same desired effect.
Most compiler vendors have form for supporting non-standard features in compilers, and either removing or altering support of those features in later releases of the compiler.
Consider changing your function so it accepts a const Number & rather than a pointer. A const reference CAN be implicitly bound to a temporary without needing to bludgeon the compiler into submission (e.g. with command line options). A non-const reference cannot.
&Number(456) is an error because the built-in & operator cannot be applied to an rvalue. Since it is an error, it is neither safe nor reliable. "What could go wrong" is that the code could be rejected and/or behave unexpectedly by a compiler which follows the C++ Standard. You are relying on your compiler supporting some C++-like dialect in which this code is defined.
You can output the address of the temporary object in various ways. For example add a member function auto operator&() { return this; } . The overloaded operator& can be applied to prvalues of class type.
Another way would be to have a function that is like the opposite of move:
template<typename T>
T& make_lvalue(T&& n)
{
return n;
}
and then you can do print(&make_lvalue(Number(456)));
If you are feeling evil, you could make a global template overload of operator&.
This is fine but..
Number *a;
print(a); // this would be a null ptr error
How I would change it is
void print(const Number num) // make the paramater const so it doesnt change
{
std::cout << num.value << std::endl; // note the . instead of -> cuz this is a reference not a pointer
}
You would remove the "&" from your code like:
Number example(123);
print(example);
print(Number(456));
and if you need to pass a pointer you just put a "*" to dereference it.
chasester

Address of return value of method

I have a get-method that returns a value:
int Foo::getValue() const
{
return value_;
}
I'm using the following code to write this value to a binary file:
void Bar::write(const Foo& foo)
{
/* some code... */
file_.write(reinterpret_cast<char*>(&foo.getValue()), sizeof(int));
}
And it seems that everything works well. But I am not sure about that &foo.getValue() thing. Will it always return an address of return value of getValue() or are there any pitfalls?
EDIT1: I dont want to create a temporary var for this.
EDIT2: Yes, it compiles and works fine.
EDIT3: write is a ostream::write
EDIT4: With /Wall and /Za it will not compile: error C2102: '&' requires l-value
The standard forbids you to take the address of an rvalue: https://stackoverflow.com/a/28459180/2642059 A compiler that is not standard compliant may allow this behavior, but assuredly that is not behavior that will be cross platform, nor is it guaranteed to succeed even between updates to the compiler that may more closely align it with the C++ standard.
Since you are not programming for a specific compiler, but for C++, finding something that works in a specific compiler should not be your objective. Finding a way to accomplish this within the standard would be preferable.
A couple easy options for doing that would be:
Turn it into an lvalue by assigning it to a temporary value. They're free! The compiler will optimize them right out
Change the return of getValue to const int& this will allow you to work with an lvalue. Since ints are typically copied by value this probably will not have repercussions in your code base, but it could
Create another method which could directly return (const char*)&value_, you could get in trouble abusing this one though so be careful
Microsoft Compiler for whatever reason has a `"feature" - it implicitly converts temporary to lvalue. You can check it by this code:
int &ref = foo.getValue();
this code as well as your should not compile. Proper code would be:
void Bar::write(const Foo& foo)
{
/* some code... */
int temp = foo.getValue();
file_.write(static_cast<const char*>(&temp), sizeof(int));
}

Is there a way to use only the object name of a class as a "default" member?

Think in a similar fashion like:
1. The bare name of an array is equivalent with the pointer to the first element, without the need to specify index 0.
2. toString() from Java makes it possible to use the name of an object as a string without calling any object method.
Now is there a way in C++ to use the name of a class object to refer to its first member?
Consider:
class Program
{
public:
int id;
char *str;
};
void function(int p)
{
//...
}
and then:
Program prog0;
function(prog0); // instead of function(prog0.id)
Any way to "hide" the member reference?
EDIT:
Why was the holyBlackCat's answer deleted? I was inclining to vote it as the best answer -- no offense, Mateusz. But he was the first to suggest conversion operator and the example was complete and simple.
In C++, such behaviour would be a cataclysm. If I understand correctly, Java tries to convert object of type A to object of type B by searching for first member in A, that is of type B or is implicitly convertible to B.
C++ wasn't designed that way. We like to write code, that is always predictable. You can achieve what you want, but for a price.
The best solution in this case would be conversion operator - consider:
class Program
{
public:
int id;
char *str;
operator int()
{
return this->id;
}
//You can have more than one!
operator const char*()
{
return this->str;
}
};
void function_int(int p)
{
}
void function_str(const char* s)
{
}
Now it is possible to do the following:
Program prog;
function_int(prog); //Equivalent of function_int(prog.id)
function_str(prog); //Equivalent of function_int(prog.str)
The price is, that if you add another int and place it before id it will not be used in conversion, because we stated in our operator explicitly, that "int content" of our class is represented by id and this member is considered when it comes to such conversion.
However, even this simple example shows some potential problems - overloading functions with integral and pointer types could result in very unpredictable behavior. When type contains conversion operators to both pointers and integers, it can get even worse.
Assume, that we have following function:
void func(unsigned long)
{
}
And we call func with argument of type Program. Which conversion operator would you expect to be called? Compiler knows how to convert Program to either int or const char*, but not unsigned long. This article on cppreference should help you to understand how implicit conversions work.
Also, as Barry pointed out, more meaningless constructs become available. Consider this one:
int x = prog + 2
What does it mean? It is perfectly valid code, though. That is why conversion operators should be dosed extremely carefully (in pre-C++11 era, there was a general advise, that every class should have at most one such operator).
Quote from MSDN:
If a conversion is required that causes an ambiguity, an error is generated. Ambiguities arise when more than one user-defined conversion is available or when a user-defined conversion and a built-in conversion exist.
Sometimes, simple solution to this problem is to mark conversion operator with explicit keyword, so you would need to change above calls to:
function_int((int)prog);
function_str((const char*)prog);
It is not as pretty as the previous form, but much safer. It basically means, that compiler is forbidden to perform any implicit conversion using operator marked as explicit. Very useful to avoid ambiguous calls, while still providing some flexibility in code - you can still very easily convert objects of one type to another, but you can be sure when and where these conversions are performed.
However, explicit conversion operators are still not supported by some compilers, as this is C++ 11 feature (for example, Visual C++ 11 doesn't support it).
You can read more about explicit keyword here.
Now is there a way in C++ to use the name of a class object to refer to its first member?
No, C++ doesn't have any reflection, so there's no way to actually determine what the "first member" is.
However, if what you really want is to get an ID for any object, you could just require that object to have that method:
template <typename T>
void function(const T& t) {
int id = t.getID();
// etc.
}
Without knowing more about your use-case, it's hard to know what to propose.

c++ function overload ambiguous

in c++
void foo(int i)
{ std::cout<<"int"<<std::endl; }
void foo(float i)
{ std::cout<<"float"<<std::endl; }
void foo(void *i)
{ std::cout<<"void *"<<std::endl; }
void foo(bool b)
{ std::cout<<"bool"<<std::endl; }
void main() { foo(0); }
when compiling this, it makes error.
in visual-studio 2008, the error is C2668:'function' : ambiguous call to overloaded function
i know why this problem occur and i know a solution that using-time typecast. but i think this is not a good solution because using this way is kill the lexicality of function overloading.
in my project, i making a lexical-object that change auto type to int,float,std::basic_string and function pointer. overload all typecast operator and creator. but when i input a 'NULL', the error C2668 occurs.
in fact it is almost no problem . the only serious problem is when using FALSE. my project is core library and so i can't guide every end-client programmer.
who knows the trick or tip of solve this problem more smart way?
As it stands right now, your code should not cause an error -- there's no ambiguity. When passing 0 (an int), it's clear that foo(int) (identity conversion) is a better fit than any of the others (even though 0 can also be implicitly converted to the types for all the other overloads).
My immediate guess would be that the code you're testing isn't quite the same as you've posted. If, for example, you did not have the overload taking int, I'd expect a error about ambiguous overloads (since, as noted above, there are implicit conversions from 0 to the types taken by all the other overloads). I've confirmed that VC++ 2008 accepts the code as is (and so do VC 2010 and the beta of VC11 and g++ 4.7.0).
As an aside I'd note that main should really return an int (though it's almost certainly unrelated to the question at hand).
C++11 corrects this by introducing a new keyword to serve as a distinguished null pointer constant: nullptr. It is of type nullptr_t, which is implicitly convertible and comparable to any pointer type or pointer-to-member type. It is not implicitly convertible or comparable to integral types, except for bool.
Maybe you could define your FALSE to ((bool)0) instead of just 0 (why not use false instead?!).
Also, if you think about it, having f(int *) and f(char *) and calling f(NULL) is ambiguous, so you need a cast anyway! The compiler doesn't magically know your intentions unless you tell it. So if something is inherently ambiguous, you just have to make it unambiguous by casting.