Is there any differece between the following implementations?
class Foo
{
int bar(int x) const
{ return x * 2; }
};
class Foo
{
inline int bar(int x) const
{ return x * 2; }
};
According to the C++ Standard (9.3 Member functions)
2 A member function may be defined (8.4) in its class definition, in
which case it is an inline member function (7.1.2), or it may be
defined outside of its class definition if it has already been
declared but not defined in its class definition.
And
3 An inline member function (whether static or non-static) may also be
defined outside of its class definition provided either its
declaration in the class definition or its definition outside of the
class definition declares the function as inline.
When the function is marked as inline, it tells the compiler to put the code of the function to the place where the function has been called from. You can have implicit and explicit inlines - member functions of classes are inlined implicitly, so you don't need to type it and in your case there is no difference.
7.1.2 Function specifiers
3 A function defined within a class definition is an inline function.
The inline specifier shall not appear on a block scope function
declaration. 94 (The inline keyword has no effect on the linkage of a function.) If the inline specifier is used in a friend
declaration, that declaration shall be a definition or the function
shall have previously been declared inline.
So, no. There is no difference.
Related
In my understanding, member functions defined inside a class definition are implicitly inline:
class X {
int f() { return 1; } // Implicitly inline.
};
int g() { return 2; } // Not implicitly inline.
I was looking for the standard quote to support this, but I can only find basic.link/7:
In addition, a member function, static data member, a named class or enumeration of class scope, or an unnamed class or enumeration defined in a class-scope typedef declaration such that the class or enumeration has the typedef name for linkage purposes ([dcl.typedef]), has the same linkage, if any, as the name of the class of which it is a member.
I can't find anything relevant in dcl.typedef that relates to simple class definitions (without typedef being involved).
Am I looking in the right place? If not, what and where is the exact standard wording?
Perhaps look in the section about, well, inline. 🤪
[dcl.inline]/4: A function defined within a class definition is an inline function.
This is actually repeated later, in the section about member functions (which also seems sensible!):
[class.mfct]/1: A member function may be defined in its class definition, in which case it is an inline member function [..]
It's in [class.mfct]:
A member function may be defined in its class definition, in which case it is an inline member function, ...
A C++ question about struct member functions.
What is the difference between f1() and f2() except their names ?
struct F{
int f1(){
return 0;
}
int f2();
};
int F::f2(){
return 0;
}
May I say f1() is inline but f2() is not ?
You are correct that f1 is inline and f2 is not, but its not just because it was defined inside the class. f2 could also be inline if it was defined as
inline int F::f2() {
return 0;
}
The C++11 spec section 9.3 says that f1 is "defined in its class definition" and f2 is "defined outside of its class definition." It then states that any function defined inside its class definition is inline, while functions defined outside of its class definition must be explicitly marked as inline (like in my example above), or else they are non-inline (like your f2).
Inside the class definition vs. outside the definition is unimportant, other than making functions implicitly inline. The concept of inside a class definition and outside a class definition only appears in 9.3.2-9.3.5, while the broader concept of "inline" appears in other parts of the spec.
Suppose I have
Base.h
class Base
{
virtual void foo() {...}
};
Derived1.h
class Derived1 : public Base
{
virtual void foo() {...}
};
Derived2.h
class Derived2 : public Base
{
virtual void foo() {...}
};
Header Derived1.h is included in multiple source files and Derived1 class is also used through Base interface. Since foo is virtual and is used polymorphic it can not be inlined. So it will be compiled in multiple obj files. How does linker then resolve this situation?
Member functions defined within class definition are implicitly inline(C++03 7.1.2.3).
Whether the function body actually gets inlined at point of calling is immaterial. But inline allows you to have multiple definitions of a function as long as all the definitions are same(which is disallowed by One definition rule)(C++03 7.1.2.2). The standard mandates that the linker should be able to link to (one or)many of these definitions.(C++03 7.1.2.4).
How does the linker do this?
The standard provisions for this by:
It mandates that the function definition should be present in each translation unit. All the linker has to do is link to the definition found in that translation unit.
It mandates that all definitions of this function should be exactly same, this removes any ambiguity of linking to a particular definition, if different definitions were to exist.
C++03 7.1.2 Function specifiers:
Para 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 for inline functions defined by 7.1.2 shall still be respected.
Para 3:
A function defined within a class definition is an inline function. The inline specifier shall not appear on a block scope function declaration
Para 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 (3.2).
Given:
template<class T>
struct test {
void foo(int b);
void testFunc( int a )
{
}
};
void test::foo(int b)
{
}
template<>
void test<float>::testFunc( int a )
{
}
void someFunction()
{
}
We know that "test::foo" has a declaration in the test class, and a definition outside the class definition.
We also know that "someFunction" has a declaration which is also its definition.
In like manner "test::testFunc" (non-specialized), has a declaration which is also its definition.
Is the specialization function "test<float>::testFunc" said to be declared with the declaration of "testFunc" inside of class "test" and defined separately, or is its declaration also the definition?
The explicit specialization in your example is a declaration that is also a definition. You could also declare it separately:
template<>
void test<float>::testFunc( int a );
and if the function was used, the linker would expect it to be defined somewhere.
The declaration inside the class is the declaration and definition of the member function template.
BTW, foo should be defined like this:
template <class T>
void test<T>::foo(int b)
{
}
I would like to add to the useful answer #Vaughn provided.
In the template definition of test, you have a non-defining member function declaration and also a defining member function declaration. But that function definition and declaration is associated with the surrounding template test<T>, and not with the class test<float> that will eventually be instantiated from it!
If you implicitly instantiate test<float> from that template, for example by using the ::-operator (scope) on it, or by creating a variable definition having that type and so on, then declarations but not necessarily the definitions of all members are also implicitly instantiated. All of them are associated with and members of test<float>.
So when you write your explicit specialization for test<float>::testFunc, because you used :: to look into the class test<float>, that class is being implicitly instantiated and with it all its member declarations.
The definition of test<float>::testFunc is only instantiated when it is required (for example when you call it).
The explicit specialization you declared then redeclares the member function that was previously implicitly instantiated and provides a definition that is associated with test<float>. It is a real function and cannot be safely defined in a header unless it is marked inline - otherwise you risk "defined more than once" errors when you include its header multiple timrs.
To summarize what declarations and definitions exist for testFunc and where they come from:
By your template definition:
test<T>::testFunc(int);
test<T>::testFunc(int) { }
Generated specialization by the compiler from test<T>::testFunc(int);
test<float>::testFunc(int);
Explicit specialization by you of test<T>::testFunc(int);
test<float>::testFunc(int);
test<float>::testFunc(int) { }
In particular, there is no generated definition of test<float>::testFunc. If there was, then your code would be ill-formed, without diagnostics required, because the generated definition would interfere with your explicit specialization that provided a definition for the same function. But such a thing can only happen if you cause its instantiation before explicitly specializing it. So if you move the explicit specialization definition into a .cpp file (if you don't want to make it inline), put an explicit specialization declaration, like #Vaughn demonstrated, into the header.
C++03 3.2.2 ...An object or non-overloaded function is used if its name appears in a potentially-evaluated expression. A virtual member function is used if it is not pure...
And then later in 3.2.3 we have: Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8).
An inline function shall be defined in every translation unit in which it is used.
Along the lines I am reading: a pure virtual function is not used. The ODR applies only to functions which are used. Doesn't this imply that the following would be legal? I am guessing the answer is no, it doesn't, but then I can't understand why.
//x.h
struct A
{
virtual void f() = 0;
};
//y.cpp
#include "x.h"
void A::f()
{
}
//z.cpp
#include "x.h"
#include <iostream>
void A::f()
{
std::cout << "Hello" << std::endl;
}
//main.cpp
#include "x.h"
struct B:A
{
virtual void f()
{
A::f();
}
};
int main()
{
A* p = new B;
p->f();
}
The two clauses are not mutually exclusive.
That a virtual function is used if it is not pure, does not mean that the converse holds. If a virtual function is pure it does not mean that it is necessarily not used. It may still be used "if its name appears in a potentially evaluated expression" such as in your example: A::f();.
This code violates ODR. A::f is multiply defined. Hence it has UB.
Multiple definitions across translation units are only allowed for the following as per $3.2/5
There can be more than one definition
of a class type (clause 9),
enumeration type (7.2), inline
function with external linkage
(7.1.2), class template (clause 14),
non-static function template (14.5.5),
static data member of a class template
(14.5.1.3), member function of a class
template (14.5.1.1), or template
specialization for which some template
parameters are not specified (14.7,
14.5.4) in a program provided that each definition appears in a different
translation unit, and provided the
definitions satisfy the following
requirements.
As #Charles Bailey pointed out, your A::f is in fact used even though it's pure virtual. But that's beside the main point.
It's not accurate that the One Definition Rule does not apply to functions that are not used. We have:
3.2p1 No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.
3.2p3 Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required.
Together, these requirements seem to imply that a used function must have exactly one definition, and an unused function (including a pure virtual function which is never explicitly called) may have either no definition or a single definition. In either case, multiple definitions for a non-inline function makes the program ill-formed.
At least, I'm quite certain that's the intent. But you may be on to a hole in the phrasing, since a very literal reading does not say anywhere that multiple different definitions of the same unused function in different translation units is ill-formed.
// x.cpp
void f() {}
void g() {}
// y.cpp
#include <iostream>
void f() {
std::cout << "Huh" << std::endl;
}
void h() {}
// z.cpp
void g();
void h();
int main() {
g();
h();
return 0;
}
This is related but off-topic: from the citations it seems there is a hole in the Standard alright: it should also say a pure virtual destructor is used, and, that it must be defined; at least if there exist any derived class objects which are destroyed or if a destructor of such is defined, since the derived class destructor must call the base destructor, implicitly it does so with the qualified::id syntax. The definition of such destructors is usually trivial but cannot be elided and cannot be generated.
[class.abstract]: "A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1)."
Your A::f is called by B::f, so there must be a single definition of A::f.