how to assign more than one different names to a function

Hi all,
So the code is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LargeInt
{
public:
  void Assign(const LargeInt &x);
  void operator=(const LargeInt &x);
}

void LargeInt::Assign(const LargeInt &x) 
{ //actual code here
}

void LargeInt::operator =(const LargeInt& x)
{ this->Assign(x);
}

Now if I call

1
2
3
4
5
  LargeInt x,y;
  x.Assign(y);//this line executes directly the function assign
  x=y; //this line calls the operator =, which in turn calls 
  //the function assign.
  // this means I lose program performance here 


I want the function Assign and the operator = to simply be made to be the same function by the compiler! How should I do this?

I need both the Assign function (because all my classes have it!) and the operator= so I can use one of my template classes (which can be applied to basic data types such as int, so it needs to be written with the operator=).

Thank you all!
Last edited on
Uhh...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LargeInt
{
public:
  void Assign(const LargeInt &x);
  void operator=(const LargeInt &x);
};

void LargeInt::Assign(const LargeInt &x) 
{ //actual code here
}

void LargeInt::operator =(const LargeInt& x)
{ //actual code here again
}


Durrr. :D

Put politely: I have never even heard of the ability to do this; and even for my answer, the only time this type of function copying mishmosh would be particularly useful would be with this (initialization after declaration because constructors can't be used for assigning because it's stuuuupid):

1
2
3
4
5
6
7
8
9
class example
{
//...
public:
example( /* le arguments */);
// ...
void initialize( /* same le arguments; in fact, same code */);
//...
};
Last edited on
Sorry mate, I dont like your solution. Still thanks for the comment! However:

If I decide, one year from now, having forgotten that I had two functions for assignment, to switch my LargeInt object from regular to hash-table arrays, and so I rewrite the Assign function but not the operator=, I will be banging my head with some weird crash in the middle of my code!

Is there any cleaner solution?
Last edited on
Make one of them inline. If the function is inlined (and the compiler follows through with the inlining) then there's little/no overhead involved with the function call -- it's like the function body is copy/pasted into the code that calls it.

1
2
3
4
5
6
7
8
9
10
11
class LargeInt
{
public:
  void Assign(const LargeInt& x);

  inline LargeInt& operator = (const LargeInt& x)
  {
    Assign(x);
    return *this;
  }
};


A few things to note:

1) Typically, operator = shouldn't be void, but should return a self reference. This allows for the a = b = c; behavior of the 'normal' assignment operator (ie: it makes your operator more intuitive)

2) If the function is to be inlined, you can't have it in the cpp file (unless it's only called from that .cpp file). You can put the function body in the class definition as I've done above, or alternatively you can do it below the class but still in the header:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LargeInt
{
public:
  void Assign(const LargeInt& x);
  LargeInt& operator = (const LargeInt& x);
};

//------------------------------------------
//  still in the header!

inline LargeInt& LargeInt::operator = (const LargeInt& x)
{
  // ...
}
Last edited on
The answer is simple, really. The code you posted will, with a high enough compiler optimization level, work as you wish. If you want to be explicit about it, add "inline" to the Assign() function definition.

1
2
3
inline void LargeInt::Assign(const LargeInt &x) 
{ //actual code here
}


or define the function inside the class definition. But 99% of the time, if the Assign() function is simple enough, the compiler will inline it for you.
But 99% of the time, if the Assign() function is simple enough, the compiler will inline it for you.


I'm not so sure. At least not unless it's implicitly inlined (in which case you are already specifying it to be inlined).

The compiler can't inline a function unless it compiles the function body. And if a function body is in a separate cpp file, the compiler never sees it (not unlil the linking stage -- at which point it's too late to inline). There have been advancements made to make compilers "smarter" so that functions can be inlined across cpp files, but I don't think it's anything you should rely on.
Pointless discussion. The penalty for one extra function call passing one pointer is minimal, so maintainability takes priority over performance. If at one point you notice that you're assigning lots of LargeInts in a very fast loop, then just don't call operator=() and just call Assign().
And why are there two versions of the same function, anyway?
Last edited on
Disch: member functions are typically the first to get inlined. You'd have to try really hard (or do something really stupid) for the compiler not to inline the function as described by the poster. See http://www.parashift.com/c++-faq-lite/inline-functions.html (especially 9.2).

tition: Trust the compiler to get it right. If you need more speed, profile the program. It's probably not those functions that are causing the problem.
Pointless discussion


True. But this is the internet. Without pointless discussions what else would there be? ;P

And there's nothing wrong with helping someone understand how inlining works.

Disch: member functions are typically the first to get inlined. You'd have to try really hard (or do something really stupid) for the compiler not to inline the function as described by the poster.


By "try really hard" do you mean "put the implementation in a cpp file"? Because that's all it takes.

The key concept here is that inline functions have to be expanded in the compiling process... whereas function bodies existing in other cpp files are not seen until the linking process (which only occurs after all individual files have been compiled). Hence a.cpp can't* inline a function that is defined in b.cpp.

*(I use the word "can't" here. Really you can, but it involves some trickery that not all common use compilers do yet).

Besides -- in C++ inline functions are pretty much expected to be in the header anyway.

To prove my point... try compiling the following program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
////////////////////////
// in a.h
void func();

////////////////////////
// in a.cpp
#include "a.h"
#include <iostream>

inline void func()
{
  std::cout << "foobar";
}

////////////////////////
// in main.cpp

#include "a.h"

int main()
{
  func();
  return 0;
}


This throws linker errors in GCC because 'func' can't be seen from main.cpp. Take out the inline keyword and it will compile, but in all likelyhood it will not be inlined.

Your link to parashift says nothing about when or where the compiler decides functions are to be inlined. It just shows some of the benefits and optimizations that can occur as a result.


tition:

Compilers are smart, but they're not magic. You generally shouldn't sweat the small stuff, and shouldn't try to "micro-optimize" code. However some basic concepts are good to know. Inlining is one of them. Don't let anyone talk you out of learning an important C++ concept.

EDIT:

To expand on that further... I think it's good to know about inlining. But even if you don't inline the function in this example, it won't matter -- there is a virtually 0% chance that this will lead to any kind of performance problem. So helios and PanGalactic are right in that you shouldn't really worry. I was just trying to show you something new.
Last edited on
I think it's fairly common practice among C++ experts to put one-liners in the header file thus allowing the compiler to inline.

1
2
3
4
5
6
7
8
9
10
11
12
13
class LargeInt {
   public:
       void Assign( const LargeInt& rhs ) 
           { *this = rhs; }
       
       LargeInt& operator=( LargeInt rhs ) {
           std::swap( v, rhs.v );
           return *this;
       }

  private:
      std::vector< unsigned > v;  
};


Or move the implementation of operator= to a .cpp file if it is large. Mine is trivial since it a) assumes only a single data member, and b) uses the copy/swap idiom for exception safety.
Last edited on
Disch: Now, now, I'm sure some of those Superman vs. {Batman|Goku} threads turned very philosophical after the first 300 or so posts.
Thank you all, I will use the inline suggestion!
Cheers!

@ helios: I needed the operator= only in order to use some template classes that work on basic data types.

I use the function Assign because using the operator= is morally wrong in the situations where I need it. So is the returning of values of the operator= (sorry Disch! When the morals of somebody conflict your common sense, you just let the fool be!).
Last edited on
Topic archived. No new replies allowed.