Virtual Functions And Inline Definition

  • Thread starter Marcelo De Brito
  • Start date
M

Marcelo De Brito

Hi!

Why is not possible to define a pure virtual inline function in C++?

For example:

class c1 {
virtual void f() = 0 {} // ERROR
virtual void g() = 0; // FINE
};

Why?

I appreciate your comments, suggestions, and etc.

Thank you!

Marcelo de Brito
 
V

Victor Bazarov

Marcelo said:
Why is not possible to define a pure virtual inline function in C++?

For example:

class c1 {
virtual void f() = 0 {} // ERROR
virtual void g() = 0; // FINE
};

Why?

Because the Standard says so (9.2, 10.4/2).

V
 
P

Phlip

Marcelo said:
Hi!

Why is not possible to define a pure virtual inline function in C++?

For example:

class c1 {
virtual void f() = 0 {} // ERROR
virtual void g() = 0; // FINE
};

Why?

I appreciate your comments, suggestions, and etc.

Because a virtual function is secretly a pointer to a function, and {} inside a
class is the same as an explicit inline. 'inline' is a hint to the compiler it
can push a method's opcodes into its call sites, without the overhead of calling
a function and jumping into a different stack frame. Methods defined inside
classes are 'inline' by default.

Taking the address of an inline function, in turn, blows away that "hint", and
forces the function to appear out-of-line. And the compiler must take the
address to generate the secret pointer for virtual dispatch.

All these rules were invented when C was young. Pure virtual is a late addition,
so it does what other abuses of inline cannot - it puts up an error if you
attempt to mix the virtual and inline concepts together.

The C++ FAQ will have an answer here too, potentially more accurate!
 
N

Neelesh

Hi!

Why is not possible to define a pure virtual inline function in C++?

It is possible (but the 'inline' request will be ignored). The
following code compiles well.

class X
{
virtual void f() = 0;
};

inline void X::f()
{
}
For example:

class c1 {
  virtual void f() = 0 {} // ERROR
  virtual void g() = 0;    // FINE

};

So what you meant was: Why is it not possible to define a pure virtual
function inside the class body (or, in other words - why is it not
possible to give a function declaraction for a pure virtual function
using "= 0" syntax and also provide a definition there).

The answer to that question is : "a function declaration cannot
provide both a pure-specifier
and a definition" (10.4p2). By "pure-specifier" the c++ standard means
the syntax "= 0".
 
V

Victor Bazarov

Phlip said:
Because a virtual function is secretly a pointer to a function, and {}
inside a class is the same as an explicit inline. 'inline' is a hint to
the compiler it can push a method's opcodes into its call sites, without
the overhead of calling a function and jumping into a different stack
frame. Methods defined inside classes are 'inline' by default.

So? A regular function can be both virtual and inline (defined in the
class definition).
Taking the address of an inline function, in turn, blows away that
"hint", and forces the function to appear out-of-line. And the compiler
must take the address to generate the secret pointer for virtual dispatch.

That shouldn't prevent the compiler from being able to substitute the
body of the function where it can.
All these rules

Which ones? That a virtual function is secretly a pointer to a function?
> were invented when C was young. Pure virtual is a late
addition, so it does what other abuses of inline cannot - it puts up an
error if you attempt to mix the virtual and inline concepts together.

The C++ FAQ will have an answer here too, potentially more accurate!

Is that a promise?

V
 
J

James Kanze

Marcelo De Brito wrote:
Because a virtual function is secretly a pointer to a
function,

Since when?
and {} inside a class is the same as an explicit
inline. 'inline' is a hint to the compiler it can push a
method's opcodes into its call sites, without the overhead of
calling a function and jumping into a different stack frame.
Methods defined inside classes are 'inline' by default.
Taking the address of an inline function, in turn, blows away
that "hint", and forces the function to appear out-of-line.

Since when? Taking the address of a function does require that
there be a single, out of line instance, but that's true of any
inline function.
And the compiler must take the address to generate the secret
pointer for virtual dispatch.

Perhaps. But what does that have to do with anything. That's
an implementation detail---the compiler's problem, not yours.
All these rules were invented when C was young.

What rules? When C was young (and even today), it didn't have
member functions, much less virtual functions. And when C was
young (until 1999, in fact), it didn't have inline functions.
Pure virtual is a late addition,

Well, it doesn't seem to be in the first edition of TC++PL. But
it's present in the ARM, and certainly predates templates and
exceptions.
so it does what other abuses of inline cannot - it puts up an
error if you attempt to mix the virtual and inline concepts
together.

Have you actually tried. Inline and virtual are orthogonal;
there's absolutely no problem making a virtual function inline
(and at least one idiom depends on it).

The only reason his first example is illegal is because the
grammar doesn't allow it. Maybe because someone had realized
that the whole concept of defining a function in the class was
wrong, and decided not to support it for anything new. But more
likely simply because no one thought to extend the grammar to
support it, and afterwards, it wasn't considered important
enough to bother with.
 
N

Neelesh

It certainly will not be ignored.
The above inline request can be honored by the compiler only if the
compiler can prove that this function is never called polymorphically.
I guess that is extremely difficult.
Yes.  And if the compiler actually ignored the inline request,
you couldn't use such a header in more than one translation
unit.

IMHO, even if the compiler actually ignores the inline request, the
very thing that "we have requested the compiler to make the function
inline" gives us all the rights of multiple (identical) defintions for
that function, one per translation unit. Quoting the standard -

7.1.2/2: A function declaration (8.3.5, 9.3, 11.4) with an inline
specifier declares an inline function. The inline specifier indicates
to the implementation that inline substitution of the function body at
the point of call is to be preferred to the usual function call
mechanism. An implementation is not required to perform this inline
substitution at the point of call; however, even if this inline
substitution is omitted, the other rules forinline functions defined
by 7.1.2 shall still be respected.

7.1.2/4: An inline function shall be defined in every translation unit
in which it is used and shall have exactly the same definition in
every case

This means that as long as we specify a function as "inline", we
should (rather we must) define it in all translation units. Hence
using such a header in multiple translation units should not be a
problem.

Thanks.
 
A

Alf P. Steinbach

* Neelesh:
The above inline request can be honored by the compiler only if the
compiler can prove that this function is never called polymorphically.
I guess that is extremely difficult.

I'm sorry, the above is meaningless.

It seems that you have misunderstood what 'inline' is about.

It has a guaranteed effect and a hinting effect; read up on it.


Cheers & hth.,

- Alf
 
N

Neelesh

* Neelesh:



I'm sorry, the above is meaningless.

It seems that you have misunderstood what 'inline' is about.

It has a guaranteed effect and a hinting effect; read up on it.

Is "hinting effect" a technical term? I'm sorry I'm not aware of it.
Did a quick googling but that couldn't help. Also, this term doesn't
seem appear in the C++ standard

My _only_ understanding about semantics of "inline" specifier is this:

-It is a request made to the compiler and the compiler is at its own
descretion whether to obey this request or not. Of course, it will
obey if it can.
- If there are any specific cases where the compiler is "forced" to
inline, then I am not aware of such cases.
- I gather that if a function is inlined, _all_ its calls must be
substituted by its definition. I am not aware if the compilers are
allowed to selectively replace the calls that it can.

Would be greatful if you could point to a relevant resource that talks
about all these, specially the "hinting effect".

Thanks
Neelesh
 
N

Neelesh

Have you actually tried.  Inline and virtual are orthogonal;
there's absolutely no problem making a virtual function inline
(and at least one idiom depends on it).

Can you please throw some more light on this? Specifically which idiom
and why wouldn't there be any problem? For example, here:

struct X
{
virtual int f() { return 1;}
};

struct Y : public X
{
int f() { return 2; }
};

int main()
{
X*x = new Y();
x->f();
}

Will a call to f() in main get inlined? If yes, then how does the
compiler understand whether to use X::f() or Y::f() ?

Thanks.
 
A

Alf P. Steinbach

* Neelesh:
Is "hinting effect" a technical term? I'm sorry I'm not aware of it.
Did a quick googling but that couldn't help. Also, this term doesn't
seem appear in the C++ standard

My _only_ understanding about semantics of "inline" specifier is this:

-It is a request made to the compiler and the compiler is at its own
descretion whether to obey this request or not. Of course, it will
obey if it can.
- If there are any specific cases where the compiler is "forced" to
inline, then I am not aware of such cases.
- I gather that if a function is inlined, _all_ its calls must be
substituted by its definition. I am not aware if the compilers are
allowed to selectively replace the calls that it can.

Would be greatful if you could point to a relevant resource that talks
about all these, specially the "hinting effect".

What you describe is the hinting effect.

The guaranteed effect is to allow multiple in-a-practical-sense-identical
definitions as long as they're in different compilation units, which as a matter
of in-practice programming allows you to define routines in header files.

The guaranteed effect is the only effect that you should be concerned about
(hinting is only for effeminate politicians, not for engineers), i.e., just
forget that hinting stuff -- although before forgetting it, note that contrary
to your description machine code inlining is decided per call, not per routine.


Cheers & hth.,

- Alf
 
J

James Kanze

The above inline request can be honored by the compiler only
if the compiler can prove that this function is never called
polymorphically. I guess that is extremely difficult.

First, the standard requires that the "request" be honored. The
way the "one definition rule" works is different for inline
functions and non-inline functions. And this is, strictly
speaking, the only formal difference. (A good compiler will, of
course, take the recommended hint into consideration. Unless it
can do better by ignoring it.) A function declared inline
*must* be defined in every translation unit it uses; a function
which in not declared inline must be defined in exactly one
translation unit, no more, no less. And a compiler which
ignores is broken, to the point of being unusable. (But I've
never seen a compiler which ignored it.)

Second, a function which is declared virtual is always called
polymorphically---i.e. the actual function called will depend on
the dynamic type of the object. How the compiler achieves this
is its business, of course, but typically, all of the compilers
I know use exactly the same mechanism as for a non-inline
function anytime they know the dynamic type. Which isn't
necessarily that rare, depending on how the object is used.
IMHO, even if the compiler actually ignores the inline
request, the very thing that "we have requested the compiler
to make the function inline" gives us all the rights of
multiple (identical) defintions for that function, one per
translation unit.

Yes. That's what the inline declarations requests.
Quoting the standard -
7.1.2/2: A function declaration (8.3.5, 9.3, 11.4) with an
inline specifier declares an inline function. The inline
specifier indicates to the implementation that inline
substitution of the function body at the point of call is to
be preferred to the usual function call mechanism. An
implementation is not required to perform this inline
substitution at the point of call; however, even if this
inline substitution is omitted, the other rules forinline
functions defined by 7.1.2 shall still be respected.
7.1.2/4: An inline function shall be defined in every
translation unit in which it is used and shall have exactly
the same definition in every case
This means that as long as we specify a function as "inline",
we should (rather we must) define it in all translation units.
Hence using such a header in multiple translation units should
not be a problem.

Yes. And. That's basically what I said: if you declare a
function inline, the compiler is required to obey that request,
and allow (or rather require) the definition to be present in
every translation unit where the function is used.
 
B

Bart van Ingen Schenau

Neelesh said:
Is "hinting effect" a technical term? I'm sorry I'm not aware of it.
Did a quick googling but that couldn't help. Also, this term doesn't
seem appear in the C++ standard

It is not a technical term, and it can be translated as "the construct
has a semantic effect that the compiler may or may not apply to the
code, at the discretion of the compiler".
My _only_ understanding about semantics of "inline" specifier is this:

-It is a request made to the compiler and the compiler is at its own
descretion whether to obey this request or not. Of course, it will
obey if it can.

Because it is a request that the compiler is not required to honour, it
is a hint.
How much effort the compiler puts in honouring this request is a QoI
(Quality of Implementation) issue. To my knowledge, there are currently
compilers available that ignore the hints of the inline specifier and
perform inline expansion for any function call where they think it is an
advantage, regardless of the presence/absence of an inline specifier for
the function.
- If there are any specific cases where the compiler is "forced" to
inline, then I am not aware of such cases.

You can safely assume there is never a requirement to actually perform
an inline expansion.
- I gather that if a function is inlined, _all_ its calls must be
substituted by its definition. I am not aware if the compilers are
allowed to selectively replace the calls that it can.

Yes, a compiler is allowed to decide on a call-by-call basis if the
function call can be expanded inline or not. If only because a strictly
conforming program will not be able to tell the difference anyway.
Would be greatful if you could point to a relevant resource that talks
about all these, specially the "hinting effect".

You yourself already quoted from the relevant resource: clause 7.1.2
Thanks
Neelesh

Bart v Ingen Schenau
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top