operator std::string() const? - c++

Can somebody tell me what precisely
operator std::string()
stands for?

It is a conversion operator that allows the object to be explicitly or implicitly casted to std::string. When such a cast occurs, the operator is invoked and the result of the cast is the result of the invocation.
As an example of an implicit cast, suppose you had a function that accepted type std::string or const std::string&, but not the given object type. Passing your object to that function would result in the conversion operator being invoked, with the result passed to the function instead of your type.

It is a cast operator. Any class that defines this type can be used anywhere a std::string is required. For instance,
class Foo {
public:
operator std::string() const { return "I am a foo!"; }
};
...
Foo foo;
std::cout << foo; // Will print "I am a foo!".
Cast operators are almost always a bad idea, since there is invariably a better way to achieve the same result. In the above case, you are better off defining operator<<(std::ostream&, const Foo&).

Related

What is the difference on const user-defined-conversions and non const?

So, if I have:
class test
{
public:
operator const int() {...}
operator int() {...}
};
Why is this following then ambiguous?:
test a;
(const int) a;
Isn't it like an explicit cast that I want a const int?
I tested this also with class types (not built in types) instead of int, and it is still ambiguous, but why?
Would be very happy if someone could explain why.
These are ambiguous.
operator const int() {...}l
operator int() {...}l
It's ambiguous because the return type isn't part of the what determines whether a method gets called and conversion types ignore const so two methods with the same signature aside will be ambiguous. However a different signature like this
operator const int() const {...}
operator int() {...}
will not be ambiguous and can be used to distinguish calls between const and non const objects. Further, this also means that the first function will not alter the object's "state" so is useful for users of the class in that it tells them the operation will not alter the object (aside from mutable members which can sometimes be useful for caching state.)
Please note that #user4581301's comment that there is rarely a reason to declare the return type const. It's going to get the type assigned to whether const or not. But this doesn't apply to reference returns.
As other's have pointed out, Conversion operators, unlike other methods, include the conversion type. But const is ignored so the following would not be ambiguous:
operator double() {...}
operator int() {...}

Syntax for using overloaded operator C++

This is an overloaded operator contained in a class:
inline operator const FOO() const { return _obj_of_type_FOO; }
I cannot for the life of me understand:
How I would invoke this operator?
What would be its return value?
[Secondary] Whether making it inline affects anything apart from efficiency?
That expression looks like a declaration of a conversion operator if Foo is a type and it is inside a class. The second const (the one closer to the opening curly bracket) means that the conversion can be called on const instances. Let us say the class is C. You can think of a conversion operator as a constructor outside a class. For example, you can't add constructors to the class std::string, but you can add a conversion operator to std::string to your classes. The result is that you can construct std::string from your class instance.
1) How to invoke the conversion operator: by constructing a value of type Foo from a C, for example:
Foo foo = c (where c is an instance of C, the class that declares the conversion operator). Mind you that the invocation of the conversion can happen implicitly. If you have, for example, void funOnFoo(Foo v); and an instace c of C, this might implicitly call operator const Foo: funOnFoo(c). Whether this actually does, depends on the usual things: Whether there are other overloads of funOnFoo, other conversions for C, etc.
2) The return value is const Foo
3) inline means the same thing as for any function, in particular, does not affect overload resolution

C++: unusual operator overloading

What an operator is overloaded here?
operator T * ()
I know that the operator method has the following structure:
type operator operator-symbol ( parameter-list )
Assume we have the following code
template<typename T> class SmartPtr
{
public:
SmartPtr(T* data): member(data) {}
T* member;
T& operator * () { return *member; } //usage: *TObj
T*& operator () () { return member; } //usage: TObj()
operator T * () { return member; } //usage: ???
};
No compilation errors if you try it on the ideone. So what is going on here?
ADD: Am I right that static_cast<T*>(TObj) makes a call of the operator T *? I've tried it here.
That's a conversion operator, which allows the class to be converted to T*. Usage:
T * p = TObj;
It's probably a bad idea for a smart pointer to provide this, as it makes it easy to accidentally get a non-smart pointer. Standard smart pointers provide explicit conversion via a get() function instead, to prevent accidental conversions.
This operator is invoked when a SmartPtr object appears in an expression, but the compiler has no functions available to resolve the usage made thereof: if it's legal to use a T* where the SmartPtr appears, the operator T*() function is called to generate one. This means my_smartptr->my_T_member can work, as can f(T*); f(my_smart_ptr_to_T);. Similarly, iostreams have an operator bool() in C++11 (operator void*() in C++03 for reasons too tedious to bother with). It's kind of the opposite of an implicit constructor from a single parameter, where should the compiler not find a valid match using the parameter, it may try to construct an object using that parameter to use instead.
operator T * () { return member; }
it is a so-called conversion operator. It converts an object of type SmartPtr to type T *. Moreover it is an implicit conversion opertaor. So when the compiler awaits an object of type T * you can use instead an object of type SmartPtr.
You could make this conversion operator explicit if you would add keyword explicit. For example
explicit operator T * () { return member; }

Operator overloading "operator T * ()" produces a comparison operator?

class Test
{
public:
operator Test * () { return NULL; };
};
int main()
{
Test test;
if (test == NULL)
printf("Wtf happened here?\n");
return 0;
}
How is it that this code compiles? How did Test get a comparison operator? Is there some implicit casting going around? What does that overloaded operator even mean (and do)?
The overloaded operator adds a conversion from Test to Test *. Since there is no comparision operator defined that takes Test and NULL as arguments, any conversion operators that exists are tried. operator Test * returns a type which is comparable with NULL, so it is used.
Yes, you've added an implicit conversion to T*, so the compiler will use it to compare against NULL.
A few other things to note:
NULL is shorthand for 0, so this means that comparison against 0 will be allowed. (This isn't true for other integer values, however. 0 is special.)
Your type also can be implicitly used in boolean contexts. That is, this is legal:
Test test;
if (test)
{
// ...
}
C++0x allows you to specify an explicit keyword for conversion operators to disallow this sort of thing.
Implicit conversion to pointer types is often pretty dubious. In addition to the pitfalls of the conversion happening in unexpected cases, it can allow dangerous situations if the object owns the returned pointer. For example, consider a string class that allowed implicit conversion to const char*:
BadString ReturnAString();
int main()
{
const char* s = ReturnAString();
// Uh-oh. s is now pointing to freed memory.
// ...
}
+1 for Baffe's response. If you're looking to somehow expose some instance of a wrapped object via * then perhaps you should overload -> instead of overloading *.
class Bar
{
public:
void Baz() { ... }
}
class Foo
{
private:
Bar* _bar;
public:
Bar* operator -> () { return _bar; }
}
// call like this:
Foo f;
f->Baz();
Just a thought.
You have not defined your own comparison thus he compiler has done one for you. you have however tried to overload the dereference operator... which I can't see why.
you want to define your operator== function
read this

Why NULL is converted to string*?

I saw the following code:
class NullClass {
public:
template<class T> operator T*() const { return 0; }
};
const NullClass NULL;
void f(int x);
void f(string *p);
f(NULL); // converts NULL to string*, then calls f(string*)
Q1> I have problems to understand the following statement
template<class T> operator T*() const { return 0; }
Specially, what is the meaning of operator T*()?
Q2> Why f(NULL) is finally triggering the f(string*)?
Thank you
what is the meaning of operator T*()?
It is a user-defined conversion operator. It allows an object of type NullClass to be converted to any pointer type.
Such conversion operators can often lead to subtle, unexpected, and pernicious problems, so they are best avoided in most cases (they are, of course, occasionally useful).
Why f(NULL) is finally triggering the f(string*)?
NULL is of type NullClass. It can't be converted to an int, but the user-defined conversion NullClass -> T* can be used to convert it to a string*, so void f(string*) is selected.
Note that this works because there is only one overload of f that takes a pointer. If you had two overloads,
void f(int*);
void f(float*);
the call would be ambiguous because the NullClass -> T* conversion can be converted to both int* and float*.
template<class T> operator T*() means that there is an implicit conversion from NullClass to T* for any T.
When you're calling f(NULL), the compiler needs to decide which overload to use. Since neither overload takes an object of type NullClass, it looks which implicit conversions exist. There is no conversion to int, but there is one to string*, so the conversion is applied and the string* overload is called.
operator Anything() overloads the "cast" operator. Whenever NullClass needs to be converted to Anything, this function will be called, and the result will be used.
In your case, Anything is T* where T can be any type (it is a template parameter), meaning a NullClass supports casting to any pointers.
Since NullClass can be cast into any pointers, including a string*. So the f(string*) version will be used.
Q1> I have problems to understand the following statement
template<class T> operator T*() const { return 0; }
Specially, what is the meaning of operator T*()?
It's an implicit conversion operator. It makes it possible to have objects of the type it belongs to implicit convert to the target type T* here. This version is a special one, since, being a template, it can convert an object of that NullClass to any pointer type.
Implicit conversion are frowned upon for good reasons. They have the bad habit of kicking in at unexpected moments, making the compiler call an unintended version of an overloaded function. Having a templatized implicit conversion operator is especially evil because templatization multiplies the possibilities.
Q2> Why f(NULL) is finally triggering the f(string*)?
See above. There is no possible conversion to int, so the implicit conversion operator kicks in and converts an NullClass object into any pointer requested.
I suppose this is intended. Usually you don't want a pointer to be converted to an integer, which is why that class has an implicit conversion into any pointer, but none to int.
That NullClass isn't all that bad, but the NULL instance of it is pure stupidity. As soon as you include any of the many headers that define the NULL macro (defined to be 0, i.e. an integer constant), the preprocessor will trample over all source and replace each usage of NULL with 0. Since you can't avoid to include this, this error renders the whole class pretty much useless.
The NuLLClass provides a conversion function to convert to a pointer. When you call f(NULL), it will try to find a way to convert NULL to a valid argument for f.
Because you can call operator T*() on NULL, it will with T=string. This fulfills the demand for f(string *). Since there is no way to convert NULL to an int, there is only one clear choice of which function to call.
Specially, what is the meaning of operator T*()?
It is a conversion operator to type T*. It allows operations such as (T*)NULL.
Q2> Why f(NULL) is finally triggering the f(string*)?
Because the compiler looks for the best match between the arguments and the method's signature, in this case choosing template<typename T> NullClass::operator T*(), where T=string.