简体   繁体   中英

Provide default arguments for subscript operator and function call operator

In the following code, I have provided default arguments for array subscript operator .

struct st 
{
    int operator[](int x = 0)
    {
        // code here
    }
};

But, compiler generated an error:

error: 'int st::operator[](int)' cannot have default arguments
     int operator[](int x = 0)

But, If I provide default arguments for function call operator.

struct st 
{
    int operator()(int x = 0)
    {
        // code here
    }
};

It's working fine.

So, I have a questions:

  • Why doesn't allowed default arguments for the array subscript operator?
  • Why does allowed default arguments for the function call operator?
  • Why doesn't allowed default argument for array subscript operator?
  • Why does allowed default argument for function call operator?

Mainly because the C++ grammar says so. According to A.4 [gram.expr]:

 postfix-expression --> postfix-expression [ expr-or-braced-init-list ] --> postfix-expression ( expression-list opt ) --> simple-type-specifier (expression-list opt) --> typename-specifier ( expression-list opt ) 

The parameters for braces are optional, the ones for brackets not. As suggested in the comment, note that brackets are required to take exactly one parameter whereas the braces can take an arbitrary number of parameters.

Also consider songyuanyao's answer for an explicit statement from the standard.

The standard states it quite clearly.

The default arguments are not allowed in operator overloading of subscripting operator .

An operator function cannot have default arguments, except where explicitly stated below. Operator functions cannot have more or fewer parameters than the number required for the corresponding operator, as described in the rest of this subclause.

and

operator[] shall be a non-static member function with exactly one parameter.

While for function call operator

operator() shall be a non-static member function with an arbitrary number of parameters. It can have default arguments.

Overloaded operators try to follow the same behavior of the built-in ones; with the built-in subscript operator the (only one) index is always required, it doesn't have default arguments . Then the overloaded operator is not allowed to have default arguments either. On the other hand, functions are always fine to take arbitrary number of parameters and have default arguments.

I suppose you are really asking why the standard allows one and not the other. The reason is mainly to do with what people expect , rather than some technical logic that precludes a default in one case but not the other:

It's a matter of what people expect the [] operator to mean. Normally it means "Get the element at [...]" where we use an int or some other type to make a specific query about a member of a collection. We are always interested in asking about a specific member, and we always have a specific query in mind.

Now consider what a default argument means. Often it means "you can specify this, but if not I'll assume this default". This works great for certain functions, and people are used to it.

Changing this would probably make a lot of people scratch their heads when they see int x = vec[]

The operators (both overloading of user-defined-types and for inbuilt types) are intended to let people use notations familiar from mathematics, logic and general usage (though << and >> have seen double-service as streaming operators, and notational compromises had to be made given the limited characters near-universally available on computers). To turn around and allow variations on the intuitive, familiar notations (such as implied arguments) seems counter-productive.

operator() is different though in that it's there to abstract away differences between "calling" (through) an object and calling a hard-coded function - it needs to support default arguments to do that properly.

You can have default arguments for array subcript operator since C++23 ( https://eel.is/c++draft/over.sub )

Overloading subscript operator for user-defined classes will now have the same semantics as defining call operator. Therefore, you can have 0, 1, 2, or multiple arguments.

struct st 
{
    int operator[](int x = 0)
    {
        // code here
    }
};

and

st obj { /* ... */ };
obj[]

are now valid.

Unfortunately, no compilers support this feature since this is the latest feature approved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM