This code actually works:
class Abstract {
virtual auto foo() -> int = 0;
};
class Concrete: public Abstract {
int foo() { cout << "blah!" << endl; return 1; }
} instance;
I understand that the function gets mangled and linked to be the same function signature, but is this kind of mixing actually legal in C++14?
While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes. Without function prototypes the compiler will not check if the functions are called correctly.
BTW there is another way to handle this whole thing: compile all your code (even your C-style code) using a C++ compiler. That pretty much eliminates the need to mix C and C++, plus it will cause you to be more careful (and possibly-hopefully!- discover some bugs) in your C-style code.
Old-style function declarations also generate warnings if you subsequently declare or define the same function with either an ellipsis or a parameter with a type that is not the same as its promoted type. The next section, C Function Definitions, shows the syntax for function definitions, including the old-style syntax.
That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e. would be the same function. Both C89/90 and C99 still officially support K&R style declarations.
auto foo()->int
and int foo()
are the same prototype expressed with different syntax, so the second function is an override of the first, and will replace it in runtime dispatch (being virtual) as usually.
The right-side return syntax, has normally another purpose, like
template<class A, class B>
auto some_combination(A a, B b) -> decltype(a+b);
otherwise requiring a more complex syntax like
temlate<class A, class B>
decltype(std::declval<A>()+std::declval<B>()) some_combination(A a,B b);
since a
and b
are not defined in the left side of the prototype.
When the return type is trivially defined, left or right placement is essentially irrelevant.
It's legal because actually you are fully defining your function.
As a minimal, working example (note the override
):
class Abstract {
virtual auto foo() -> int = 0;
};
class Concrete: public Abstract {
int foo() override { return 1; }
} instance;
int main() { }
Here the return type isn't deduced, it's explicitly declared by means of a trailing return type.
It's equivalent to:
class Abstract {
virtual int foo() = 0;
};
It would have been different if you were using this:
class Abstract {
virtual auto foo() = 0;
};
Here template deduction is involved and virtual functions cannot have deduced return type (that is more or less the error string from GCC).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With