Is the Return Type Part of the Function Signature

Is the return type part of the function signature?

Normal functions do not include the return type in their signature.

(note: i've rewritten this answer, and the comments below don't apply to this revision - see the edit-history for details).

Introduction

However, the matter about functions and function declarations in the Standard is complicated. There are two layers that have to be considered:

  • Declarations
  • Entities

The so-called function declaration may declare a function entity or a template entity. If a function entity is declared, then you either have to do with an explicit specialization of a function template (with all arguments specified), or a declaration of an ordinary function. If a template entity is declared, then you are declaring a primary function template, or an explicit specialization where some arguments are not specified. (This is very similar to the relation of "object declaration" and objects or references: The former may declare either an object or a reference. So an object declaration may not necessarily declare an object!).

The Standard defines the signature of a function to include the following at 1.3.10:

The types of its parameters and, if the function is a class member, the cv- qualifiers (if any) on the function itself and the class in which the member function is declared. The signature of a function template specialization includes the types of its template arguments. (14.5.5.1)

It's missing the return type in this definition, which is part of the signature of a function template specialization (i.e a function declaration that declares a function which is a specialization of a template), as pointed out by 14.5.5.1 (recent C++0x working papers fixed that already to mention the return type in 1.3.10 too):

The signature of a function template specialization consists of the signature of the function template and of the actual template arguments (whether explicitly specified or deduced).

The signature of a function template consists of its function signature, its return type and its template parameter list.

So what exactly does a signature contain, again?

So, when we ask about the signature of a function, we have to give two answers:

  • For functions that are specializations of function templates, the signature includes the return type.
  • For functions that are not specializations, the return type is not part of the signature.

Notice, however, that the return type, in any case, is a significant part of the type of a function. That is, the following is not valid:

void f();
int (*pf)() = &f; // different types!

When is an overload invalid if only the return type differs?

Major compilers currently reject the following code:

int f();
double f(); // invalid

But accept the following code:

template<typename T> int f();
template<typename T> double f(); // invalid?

However, the Standard does forbid a function declaration that only differs in the return type (when defining when an overload is valid, and when not). It does not define precisely what "differs only by return type" means, though.


Standard paragraph references:

  • When can a function declaration be overloaded: 13.1
  • What is a function declaration: 7/2 and 7/5
  • What is the signature of a function template/specialization: 14.5.5.1

For reference, here is what the most recent C++0x draft n3000 says about "signature" in 1.3.11, which is much more complete in its coverage of the different type of entities:

the name and the parameter type list (8.3.5) of a function, as well as the class or namespace of which it is a member. If a function or function template is a class member its signature additionally includes the cv-qualifiers (if any) and the ref-qualifier (if any) on the function or function template itself. The signature of a function template additionally includes its return type and its template parameter list. The signature of a function template specialization includes the signature of the template of which it is a specialization and its template arguments (whether explicitly specified or deduced). [ Note: Signatures are used as a basis for name mangling and linking. — end note ]

The return type / return value is part of the signature of the method?

The return value of a method must strictly follow the return type of its method so you could technically use the two terms interchangeably when talking about method signatures which it looks like they've done in the excerpt, albeit confusing.

In the case of method overloading the return type is not considered part of the method signature as the compiler cannot determine on return type alone which methods to use and as such the return type is not included in the method signature. For example consider the following overloaded methods where only the return type differs:

public int GetResult() { }
public double GetResult() { }

If we were to call this method, how would the compiler know which method to use?

var result = GetResult();

However as the language definition states: the method name, number of generic types, number of and type of each formal parameter and out/ref/value parameters are part of the method signature when overloading so for example if you wanted to overload then you could do:

public int GetResult() { }
public int GetResult(int x) { }

There are cases where the return type of a method is considered part of the signature such as delegates since the method must have the same return type as the delegate declaration. As per the C# specification:

In the context of method overloading, the signature of a method does not include the return value. But in the context of delegates, the signature does include the return value. In other words, a method must have the same return type as the delegate.

Does a method's signature in Java include its return type?

Quoting from Oracle Docs:

Definition: Two of the components of a method declaration comprise the method signature—the method's name and the parameter types.

Sample Image

Since the question was edited to include this example:

public class Foo {
public int myMethod(int param) {}
public char myMethod(int param) {}
}

No, the compiler won't know the difference, as their signature: myMethod(int param) is the same. The second line:

    public char myMethod(int param) {}

will give you can error: method is already defined in class, which further confirms the above statement.

Why is the return type of method not included in the method-signature?

This is done because the compiler would not be able to figure out the overload in all contexts.

For example, if you call

String x = method1("aaa");

the compiler knows that you are looking for the second overload. However, if you call

method1("aaa");

like this, the compiler has no idea which one of the two methods you wanted to invoke, because it is OK to call a method returning String and discard the result. To avoid ambiguities like this, Java prohibits overloads that differ solely on the return type.

Is the const return type required in both function declaration and definition?

I was wondering if there's a specific feature in C++ which requires it
to have const return types in both the definition and declaration?

No. Actually, it's the other way around. There is a specific feature in C that drops that requirement.

From C documentation of function declarations @ cppreference.com:

The return type cannot be cvr-qualified: any qualified return type is adjusted to its unqualified version for the purpose of constructing the function type.

In your C example, even though you think you declared const int test();, the const qualification is dropped and you actually declared int test();. Hence declaration and definition match.

C++ does not drop cv-qualification from return types.

In typescript, what is the return type of a function that returns a void function?

Typescript will infer the return type, and the easiest way to find out what it infers is to hover over the symbol:

Sample Image

As we can see the return type is () => void. Which is a function signature of a function with no argument (the () part), that returns void (the => void part).

function mysteryTypeFunction(): () => void {
return function(): void {
console.log('Doing some work!');
};
}

is return-type signature in function overloading useless?

When I call your function, I get the following types returned:

// a is number
var a = pickCard([{ suit: 'hearts', card: 1 }]);

// b is {suit: string; card: number; }
var b = pickCard(1);

This saves me from having to specify it manually:

// a is number
var a: number = pickCard([{ suit: 'hearts', card: 1 }]);

// b is {suit: string; card: number; }
var b: {suit: string; card: number; } = pickCard(1);

If you were to get them "the wrong way around", you would indeed get errors about the types:

// a is number
var a: {suit: string; card: number; } = pickCard([{ suit: 'hearts', card: 1 }]);

// b is {suit: string; card: number; }
var b: number = pickCard(1);

So the overload is indeed being picked based on the argument you pass - and the return type is adjusted based on the selected overload.

View this example on the TypeScript Playground.

Method Signature in C#

Return type is not part of the method signature in C#. Only the method name and its parameters types (but not the parameter names) are part of the signature. You cannot, for example, have these two methods:

int DoSomething(int a, int b);
string DoSomething(int a, int b);

To be clear: Methods cannot be overloaded based on their return type. They must have a unique name, unique parameter types, or pass their arguments differently (e.g. using out or ref).

Edit: To answer your original question, the method signature for your method is:

DoSomething(int, int)

Note that this all applies to normal methods. If you're talking about delegates, then you should see keyboardP's answer. (Short version: return type IS part of the signature for a delegate).

C++ identical method signature but different return type

The two functions are actually not the same. Only the second function is declared as a const member function. If the object that the member is called from is const, the latter option is used. If the object is non-const, the first option is used.

Example:

void any_func(const Type *t)
{
something = t->value(); //second `const` version used
}

void any_func2(Type *t)
{
something = t->value(); //first non-`const` version used
}

If both functions were declared non-const or both were declared const, the compiler would (should, anyway) complain.



Related Topics



Leave a reply



Submit