0

I have a question related to operator overloading, and it is easy to define a class as well as its operator overloading function as the following codes illustrate:

typedef std::vector<std::vector<int> > ARRAY; 


class ABC
{
public:
    ABC():a(0)
    {
    };
    int a;
    ABC& operator = (int value)
    {
        a = value;
        return *this;
    }
    ABC(int value)
    {
        a = value;

    }
};


void obtain_priority_array(const std::vector<double> &weighting, const ABC &priority_array=NULL)
{

}

int main()
{
    vector<double> weighting;
    weighting.push_back(0.8);
    weighting.push_back(0.9);
    weighting.push_back(0.6);
    weighting.push_back(0.3);
    weighting.push_back(0.5);

    ABC test;
    obtain_priority_array(weighting, test);

    return 0;
}

In the above example, class ABC redefined operator = so that the function void obtain_priority_array(const std::vector<double> &weighting, const ABC &priority_array=NULL) can have a default argument const ABC &priority_array=NULL. My question is if the last parameter in the function comes from STL, for example, const std::vector<int> &priority_array=NULL, how can we redefine operator =. Thanks!

EDIT: void obtain_priority_array(const std::vector &weighting, const std::vector<int> &sample=NULL) failed!

feelfree
  • 11,175
  • 20
  • 96
  • 167
  • 2
    Why don't you change your function to takes pointers, instead of references? If you want to pass only `NULL` as default parameter. – Kiril Kirov Oct 11 '12 at 16:31
  • By the way, `operator=` is not being called for the default argument. The constructor taking an int is: http://liveworkspace.org/code/84813303faa93e2b1359fa90c21adba8 – chris Oct 11 '12 at 16:33
  • References were designed to avoid being NULL. Trying to pass NULL as a reference seems to be a bad code conception. – tomahh Oct 11 '12 at 16:34
  • @chris Yes, then my question is for STL components, how can I define a constructor for STL vector? – feelfree Oct 11 '12 at 16:36
  • 1
    @feelfree, Look at this: http://en.cppreference.com/w/cpp/container/vector/vector. The only constructor that can take `NULL` is explicit, so you'd need something along the lines of `const std::vector &priority_array = std::vector(NULL)`, which translates to an empty vector. If it should translate to no vector, you must use a pointer. – chris Oct 11 '12 at 16:38
  • @chris Thanks, it works. Could you answer this question? I think you have given me the right answer. – feelfree Oct 11 '12 at 16:51
  • @chris There is no vector constructor that can take a null pointer. `std::vector(nullptr)` [will not compile](http://liveworkspace.org/code/82c8042d4ba62b90de9fe59d7994a0b9). `std::vector(NULL)` will compile only because `NULL` is `0`. – Praetorian Oct 11 '12 at 16:54
  • @Prætorian, I realize that. I kind of tried to point it out a little with the empty vector part thrown in. I was a bit more explicit in my answer. – chris Oct 11 '12 at 16:59
  • @chris Good to see an answer from you, instead of comments only :-). Even in the answer though, there's no reason for the argument, just default constructing the vector is enough. But I'm glad you replaced the `NULL` with `0`, since the former is confusing. – Praetorian Oct 11 '12 at 17:01
  • @Prætorian, I guess, but I was keeping similar syntax to what the OP was providing to it right now, and it is only one extra character. I don't think you can default it without the whole extra `std::vector` in there, can you? Maybe it could be a different use for `default`. `const std::vector & = default` has a nice ring. – chris Oct 11 '12 at 17:03

3 Answers3

3

References cannot be NULL, your problem has nothing to do with operator overloading. If you want to be able to handle NULL as the default value, switch the parameter type from reference to pointer.

void obtain_priority_array( const std::vector<double>& weighting, 
                            const ABC *priority_array = NULL)
{
  if( priority_array == NULL ) {
    // blah
  } else {
    // more blah
  }
}

Another option is to use something like Boost.Optional to represent the optional parameter.

typedef boost::optional<ABC> maybe_ABC;
void obtain_priority_array( const std::vector<double>& weighting, 
                            const maybe_ABC& priority_array = maybe_ABC() )
{
  if( !priority_array ) {
    // blah
  } else {
    // more blah
  }
}
Praetorian
  • 106,671
  • 19
  • 240
  • 328
3

Your misconceptions start with the proposal to add operator= to allow for a default argument of that type. In your example, it is not operator= being called, but ABC(int).

The reason your code isn't being accepted when using std::vector is that NULL translates to 0 (at least it does almost all of the time you'll see it), and the only constructor of std::vector that can take 0, the one taking a count of how many items, is marked explicit.

To fix the immediate problem, the syntax could be changed to:

const std::vector<int> &priority_array = std::vector<int>(0)

However, this introduces different semantics. By your use of NULL, it looks like you were expecting it to represent no vector. This version will provide an empty vector for use if none is given. It will not be no vector at all. If you want that distinction, you should use boost's optional library, or a simple pointer, as references are not the right tool.

chris
  • 60,560
  • 13
  • 143
  • 205
1

When you use = to create a reference, you're not calling operator= at all. You're initializing the reference.

Instead of using NULL you can create a static instance of the class to represent a null value.

static const ABC ABC_NULL;

void obtain_priority_array(const std::vector<double> &weighting, const ABC &priority_array=ABC_NULL)
{
    if (&priority_array == &ABC_NULL) // the default was used

Of course it would be easier to just use a pointer instead of a reference.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Thanks, I got it. The problem now I face is that if **std::vector priority_array** is an argument of the function obtain_priority_array, and the function expects a default constructor for **std::vector priority_array**, what should I do? – feelfree Oct 11 '12 at 16:47
  • @chris has given me the right answer: const std::vector &priority_array = std::vector(NULL). Thanks anyway! – feelfree Oct 11 '12 at 16:52