Operator overloading in template in C++ - c++

I read following code from somewhere:
template<class T> class A {
T a;
public:
A(T x):a(x) {}
operator T() const {return a;} // what is point here?
};
int _tmain(int argc, _TCHAR* argv[])
{
A<int> a = A<int>(5);
int n = a;
cout << n;
return 0;
}
What does below line mean?
operator T() const {return a;}

operator T() const {return a;}
This is the typecast operator. It'll implicitly convert the class instance to T. In the example code you've posted this conversion is being performed at the line
int n = a;

It means if you want to convert an instance into a T you can use this operator, which here returns a copy of the private member.
In your example code that is how you can assign a, which is of type A<int> to an int directly. Try removing the operator T() and see how that fails to compile, with an error about assigining A<T> to an int.
With the non explicit constructor (the opposite of marking a constructor explicit) there too it makes this type behave a lot like the template type itself in a number of circumstances. In effect you've wrapped a T inside another class that behaves like a T when it needs to. You could extend this to do other, more useful things like monitoring/logging/restricting the use of real instances by hiding them behind something which controlled them.
Also notice how you can change A<int> a = A<int>(5); to simply A<int> a = 5; because of the implicit constructor.

It's basically making a functor - which is an object with function semantics. That means you can call the object just like a function as a replacement in places where you may have used a function - its a generic programming concept.
It's beneficial because you can have multiple instances of that function-object (functor) and they can each maintain their own state, where as if you had a straight-up function then it could only maintain state via static variables, and it would thus not be re-entrant (you only ever get one instance of a static variable).
Functors are heavily used in STL algorithms as an extra optional parameter.

Related

lvalue and rvalue getter, is it possible to remove them?

Let's say we have this simple class
struct MyClass {
const std::string &getString() const & {
return m_string;
}
std::string getString() && {
return std::move(m_string);
}
private:
std::string m_string;
};
As we can see, the m_string acts as a non mutable variable in the sense that we cannot modify it.
This structure also preserve the fact that if we move one instance of MyClass to another, the m_string attribute will be moved as well.
Now, we are going to try to refactor the prior structure :
struct MyClass {
std::string m_string;
};
Here, we keeps the fact that we can access it or move it, but we lose the "immutability"... So I tried to write it like that :
struct MyClass {
const std::string m_string;
};
Here we get the immutability thing, however, we lose the potential optimization when we move the object...
So, is it possible to have a behavior similar to the first code, without writing all the getter?
EDIT: the std::string is just for example, but the idea must be usable with all kind of objects
So, is it possible to have a behavior similar to the first code, without writing all the getter?
I can't think of any.
Having said that, the overhead of writing getters and setters for member variables is not such a big burden that I would spend too much time thinking about it.
However, there are some who think that getters and setters of member variables don't add enough protection to a class to even worry about them. If you subscribe to that line of thinking, you can get rid of the getters and setters altogether.
I have used the "no getters and setters" principle for containers of data enough times that I find it natural in many use cases.
You can implement this behavior using a template wrapper type. It seems you want a type that works well with copy and move construction and assignment, but which only provides const access to the wrapped object. All you should need is a wrapper with a forwarding constructor, an implicit conversion operator and dereferencing operators (to force the conversion when implicit conversion doesn't work) :
template<class T>
class immutable
{
public:
template<class ... A>
immutable(A&&... args) : member(std::forward<A>(args)...) {}
public:
operator const T &() const { return member; }
const T & operator*() const { return member; }
const T * operator->() const { return &member; }
private:
T member;
};
This will work well with compiler generated copy and move construction and assignment. The solution is not 100% transparent however. The wrapper will implicitly convert to a reference to the wrapped type, if the context allows it :
#include <string>
struct foo
{
immutable<std::string> s;
};
void test(const std::string &) {}
int main()
{
foo f;
test(f.s); // Converts implicitly
}
But it will need an extra dereference to force the conversion in contexts where implicit conversion will not work :
int main()
{
foo f;
// std::cout << f.s; // Doesn't work
std::cout << *(f.s); // Dereference instead
// f.s.size(); // Doesn't work
f.s->size(); // Dereference instead
}
There was a proposal to add overloading of the . operator, which would allow most cases to work as intended, without a dereferencing. But I'm not sure what the current state of the proposal is.
The solution is to use std::shared_ptr<const std::string>. A shared pointer to a immutable object has value semantic. Copy-on-write can be achieved using shared_ptr::unique(). See Sean Parent presentation 47:46 https://youtu.be/QGcVXgEVMJg.
If only you are willing to declare the copy and defuslt ctor as =default and define the move ctor with const_cast cheat.
MyClass::Myclass()=default;
MyClass::Myclass(Myclass const&)=default;
MyClass::Myclass(Myclass && m)
: m_string{std::move(const_cast<std::string&>(m.m_string))}{};

Detect assignment of base class to reference pointing at derived class

I'm currently investigating the interplay between polymorphic types and assignment operations. My main concern is whether or not someone might try assigning the value of a base class to an object of a derived class, which would cause problems.
From this answer I learned that the assignment operator of the base class is always hidden by the implicitely defined assignment operator of the derived class. So for assignment to a simple variable, incorrect types will cause compiler errors. However, this is not true if the assignment occurs via a reference:
class A { public: int a; };
class B : public A { public: int b; };
int main() {
A a; a.a = 1;
B b; b.a = 2; b.b = 3;
// b = a; // good: won't compile
A& c = b;
c = a; // bad: inconcistent assignment
return b.a*10 + b.b; // returns 13
}
This form of assignment would likely lead to inconcistent object state, however there is no compiler warning and the code looks non-evil to me at first glance.
Is there any established idiom to detect such issues?
I guess I only can hope for run-time detection, throwing an exception if I find such an invalid assignment. The best approach I can think of just now is a user-defined assigment operator in the base class, which uses run-time type information to ensure that this is actually a pointer to an instance of base, not to a derived class, and then does a manual member-by-member copy. This sounds like a lot of overhead, and severely impact code readability. Is there something easier?
Edit: Since the applicability of some approaches seems to depend on what I want to do, here are some details.
I have two mathematical concepts, say ring and field. Every field is a ring, but not conversely. There are several implementations for each, and they share common base classes, namely AbstractRing and AbstractField, the latter derived from the former. Now I try to implement easy-to-write by-reference semantics based on std::shared_ptr. So my Ring class contains a std::shared_ptr<AbstractRing> holding its implementation, and a bunch of methods forwarding to that. I'd like to write Field as inheriting from Ring so I don't have to repeat those methods. The methods specific to a field would simply cast the pointer to AbstractField, and I'd like to do that cast statically. I can ensure that the pointer is actually an AbstractField at construction, but I'm worried that someone will assign a Ring to a Ring& which is actually a Field, thus breaking my assumed invariant about the contained shared pointer.
Since the assignment to a downcast type reference can't be detected at compile time I would suggest a dynamic solution. It's an unusual case and I'd usually be against this, but using a virtual assignment operator might be required.
class Ring {
virtual Ring& operator = ( const Ring& ring ) {
/* Do ring assignment stuff. */
return *this;
}
};
class Field {
virtual Ring& operator = ( const Ring& ring ) {
/* Trying to assign a Ring to a Field. */
throw someTypeError();
}
virtual Field& operator = ( const Field& field ) {
/* Allow assignment of complete fields. */
return *this;
}
};
This is probably the most sensible approach.
An alternative may be to create a template class for references that can keep track of this and simply forbid the usage of basic pointers * and references &. A templated solution may be trickier to implement correctly but would allow static typechecking that forbids the downcast. Here's a basic version that at least for me correctly gives a compilation error with "noDerivs( b )" being the origin of the error, using GCC 4.8 and the -std=c++11 flag (for static_assert).
#include <type_traits>
template<class T>
struct CompleteRef {
T& ref;
template<class S>
CompleteRef( S& ref ) : ref( ref ) {
static_assert( std::is_same<T,S>::value, "Downcasting not allowed" );
}
T& get() const { return ref; }
};
class A { int a; };
class B : public A { int b; };
void noDerivs( CompleteRef<A> a_ref ) {
A& a = a_ref.get();
}
int main() {
A a;
B b;
noDerivs( a );
noDerivs( b );
return 0;
}
This specific template can still be fooled if the user first creates a reference of his own and passes that as an argument. In the end, guarding your users from doing stupid things is an hopeless endeavor. Sometimes all you can do is give a fair warning and present a detailed best-practice documentation.

Assignment operator=

Suppose I have a class called Complex with 2 parameters real and imag. I want to overload the =(assignment) operator so that I could copy the value from the real parameter and assign it to an int.
If my main would look something like;
Complex z(1, 2);
int a = z;
I want a to be equal to 1.
How can I implement this function/method?
Use cast operator:
//Declaraion
class Complex {
operator int();
}
//Definition
Complex::operator int() {
return real_number;
}
Cast operator can implicitly convert a class instance to a certain type that is defined. It is a handy tool, but sometimes can be dangerous and vulnerable, and hard to debug.
When you define the assignment operator you are instructing the compiler on what to do when a value of possibly a different type is assigned to and instance of your class.
In this case instead you want to define what to do when an instance of your class is assigned to a variable of a different non-class type and this is not possible however. In other words it's the receiving instance that defines what to do in case of an assignment and you can customize this only for class types.
Something quite similar is instead to define how an instance of your class should be convertible to another type, e.g. how to convert a complex to an integer, and this conversion will be used also in case of assignment:
struct complex {
double real, imag;
...
operator int () const { return int(real); }
};
It isn't ideal to have code that reads as an assignment of types from different equivalence classes. It is correct that one should use casting instead, but the casting must be made explicit in C++11:
struct Complex {
double r, i;
...
explicit operator int () const { return int(r); }
};
Complex c = { 1.1, 2.2 };
float a = c; // fails with explicit
float a = (float)c; // fails with explicit
int a = c; // fails with explicit
int a = (int)c; // compiles with explicit
Do you really need to define a class for complex? It's part of standard library
Even you can see <complex> (#include <complex>) to find the operators and definitions overloaded
See more here

c++ variable assignment, is this a normal way..?

This may be a silly question, but still I'm a bit curious...
Recently I was working on one of my former colleague projects, and I've noticed that he really loved to use something like this:
int foo(7);
instead of:
int foo = 7;
Is this a normal/good way to do in C++ language?
Is there some kind of benefits to it? (Or is this just some silly programming style that he was into..?)
This really reminds me a bit of a good way how class member variables can be assigned in the class constructor... something like this:
class MyClass
{
public:
MyClass(int foo) : mFoo(foo)
{ }
private:
int mFoo;
};
instead of this:
class MyClass
{
public:
MyClass(int foo)
{
mFoo = foo;
}
private:
int mFoo;
};
For basic types there's no difference. Use whichever is consistent with the existing code and looks more natural to you.
Otherwise,
A a(x);
performs direct initialization, and
A a = x;
performs copy initialization.
The second part is a member initializer list, there's a bunch of Q&As about it on StackOverflow.
Both are valid. For builtin types they do the same thing; for class types there is a subtle difference.
MyClass m(7); // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
// then uses MyClass(const MyClass&) to copy the
// temporary object into n
The obvious implication is that if MyClass has no copy constructor, or it has one but it isn't accessible, the attempted construction fails. If the construction would succeed, the compiler is allowed to skip the copy constructor and use MyClass(int) directly.
All the answers above are correct. Just add that to it that C++11 supports another way, a generic one as they say to initialize variables.
int a = {2} ;
or
int a {2} ;
Several other good answers point out the difference between constructing "in place" (ClassType v(<constructor args>)) and creating a temporary object and using the copy constructor to copy it (ClassType v = <constructor arg>). Two additional points need to be made, I think. First, the second form obviously has only a single argument, so if your constructor takes more than one argument, you should prefer the first form (yes, there are ways around that, but I think the direct construction is more concise and readable - but, as has been pointed out, that's a personal preferance).
Secondly, the form you use matters if your copy constructor does something significantly different than your standard constructor. This won't be the case most of the time, and some will argue that it's a bad idea to do so, but the language does allow for this to be the case (all surprises you end up dealing with because of it, though, are your own fault).
It's a C++ style of initializing variables - C++ added it for fundamental types so the same form could be used for fundamental and user-defined types. this can be very important for template code that's intended to be instantiated for either kind of type.
Whether you like to use it for normal initialization of fundamental types is a style preference.
Note that C++11 also adds the uniform initialization syntax which allows the same style of initialization to be used for all types - even aggregates like POD structs and arrays (though user defined types may need to have a new type of constructor that takes an initialization list to allow the uniform syntax to be used with them).
Yours is not a silly question at all as things are not as simple as they may seem. Suppose you have:
class A {
public:
A() {}
};
and
class B {
public:
class B(A const &) {}
};
Writing
B b = B(A());
Requires that B's copy constructor be accessible. Writing
B b = A();
Requires also that B's converting constructor B(A const &) be not declared explicit. On the other hand if you write
A a;
B b(a);
all is well, but if you write
B b(A());
This is interpreted by the compiler as the declaration of a function b that takes a nameless argument which is a parameterless function returning A, resulting in mysterious bugs. This is known as C++'s most vexing parse.
I prefer using the parenthetical style...though I always use a space to distinguish from function or method calls, on which I don't use a space:
int foo (7); // initialization
myVector.push_back(7); // method call
One of my reasons for preferring using this across the board for initialization is because it helps remind people that it is not an assignment. Hence overloads to the assignment operator will not apply:
#include <iostream>
class Bar {
private:
int value;
public:
Bar (int value) : value (value) {
std::cout << "code path A" << "\n";
}
Bar& operator=(int right) {
value = right;
std::cout << "code path B" << "\n";
return *this;
}
};
int main() {
Bar b = 7;
b = 7;
return 0;
}
The output is:
code path A
code path B
It feels like the presence of the equals sign obscures the difference. Even if it's "common knowledge" I like to make initialization look notably different than assignment, since we are able to do so.
It's just the syntax for initialization of something :-
SomeClass data(12, 134);
That looks reasonable, but
int data(123);
Looks strange but they are the same syntax.

Operator [] overloading

I have the following code:
class A
{
public:
A() {};
void operator[](int x)
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.operator[](0);
a[0];
}
Both calls work, but I want to know whether there is any difference. Is one more efficient than the other? Do other things happen(besides executing the code in the overloaded operator) in either case?
EDIT:
Is there a case why you would want to write a.operator instead of just []. What's the point of overloading if you're not using the short syntax?
Both calls are identical. All the operators can be called with an explicit .operator## syntax, where ## stands for the actual operator symbol.
It is the literal operators like a + b that are just syntactic sugar for a.operator+(b) when it comes to classes. (Though of course for primitive types that is not the case.)
Note that your []-operator is not very typical, since it is usually used to return a reference to something -- but it's up to you how to implement it. You're restricted to one single argument, though, unlike operator().
The explicit operator[] (and any other explicit operator) is used in an inheritence heirarchy, where you are trying to call operator[] on a base class. You can't do that using the normal [], as it would result in a recursive function call. ie; you might use something like this:
struct Base {
void operator[] (int i) { }
};
struct Derived : public Base {
void operator[] (int i)
{ Base::operator[](i); }
};
Other than having to type another 11 characters, there is no functional difference between the two.
They are completely equivalent - just in once case C++ adds syntactic sugar that makes your code prettier. You can call all overloaded operators explicitly - the effect will be the same as when they are called implicitly and the compiler redirects calls to them.
No there is no difference between both versions from performance point of view. a[0] is more readable.
Also, the operator [] is typically defined as,
Type& operator[](const int x)
{
return v[x]; // Type 'v' is member variable which you are accessing for array
}