In this code:
struct tmp
{
int va = 0;
tmp() = default;
bool operator==(const tmp& rhv) const = default; //(in c 20)
};
Are the constructor tmp()
and operator==
inline functions, even though I didn't add the "inline" keyword in front of them?
If the answer is yes, what will happen if add a "inline" in front of them?
And can I force them to be regular functions? (Although I don't know which object file can store them.)
CodePudding user response:
Are the constructor tmp() and operator== inline functions, even though I didn't add the "inline" keyword in front of them?
Yes, this can be seen from dcl.fct.def.def.default#3 which states:
An explicitly-defaulted function that is not defined as deleted may be declared constexpr or consteval only if it is constexpr-compatible ([special], [class.compare.default]). A function explicitly defaulted on its first declaration is implicitly inline ([dcl.inline]), and is implicitly constexpr ([dcl.constexpr]) if it is constexpr-compatible.
(emphasis mine)
And since both tmp::tmp()
as well as bool tmp::operator==(const tmp&) const
are explicitly defaulted on their respective first declaration, both of them are implicitly inline.
If the answer is yes, what will happen if add a "inline" in front of them?
As both are already implicitly inline, the effect of explicitly adding inline
infront of them will be the same as not adding inline
explicitly.
And can I force them to be regular functions?
You can avoid them being implicitly inline by not explicitly defaulting the member functions in their first declarations so that the above quoted rule does not apply. For example,
struct tmp
{
int va = 0;
tmp(); //don't default here in the first declaration
};
tmp::tmp() = default;
int main()
{
tmp t; //the default ctor is not "implicitly inline"
}
CodePudding user response:
I am not sure if this is what you are looking for, but you can avoid at least one of the two meanings of inline
(read this excellent answer the two meanings: https://stackoverflow.com/a/47931884/11829247).
If you have this in the .h file:
struct Thing
{
...
~Thing();
}
And then in the .cpp file you have: Thing::~Thing() = default;
then at least the linker part of inline
s meaning is disabled, and the class now have to obey the one definition rule.
I use this in a program where I want to have an opaque pimpl class, so I have:
class Thing
{
struct Fsm; // forward declare class
std::unique_ptr<Fsm> fsm; // pimpl with that class
}
If I leave the destructor of Thing
undeclared or just =default
it there, then this errors out because the compiler cannot construct a destructor for the unique_ptr
because Fsm
is an incomplete class.
But if the destructor of Thing
is "delayed" to the .cpp file, where I also include the header for Fsm
, then all is good and the compiler can make the default destructor for me.