If I have a virtual function that carries an attribute
[[nodiscard]] virtual bool some_function() = 0;
Does that attribute get implicitly applied to overrides of that function?
bool some_function() override;
Or do I need the attribute again?
[[nodiscard]] bool some_function() override;
Subclasses can have two kinds of attributes: local and inherited. A local attribute is one that is defined on the subclass. An inherited attribute is one that is inherited from a parent product class. You customize an inherited attribute domain by editing its definition at the subclass level.
Basically: an attribute is not a member of the class or a constructor, so it can't be inherited.
Function attributes are extensions implemented to enhance the portability of programs developed with GNU C. Specifiable attributes for functions provide explicit ways to help the compiler optimize function calls and to instruct it to check more aspects of the code.
Constructor cannot be inherited but a derived class can call the constructor of the base class. In C++, friend is not inherited. If a base class has a friend function, then the function does not become a friend of the derived class(es).
I sent an email to the C++ committee, specifically the Core working group, and provided the above example.
CoryKramer
It is currently unclear from the standard if attributes applied to virtual functions are inherited.
Response:
They are not. For them to be inherited, the Standard would have to explicitly say so, and it does not.
CoryKramer:
[After providing above code example] In the above example, I would expect both lines calling
foo()
to emit a compiler warning. I would hope that the attribute applies to all derived functions for consistency.
Response:
That's one perspective. Another is that, especially with covariant return types where the derived function returns a different type from that of the base function, it might very well be useful to make the base return type
[[nodiscard]]
but not the derived return type. There's currently no way to mark the derived function as not-[[nodiscard]]
.More generally, it seems reasonable to get a different set of attributes when calling a derived function from those you get when calling the base function. If you know you have a derived class object, you have more specific information and behavior than if all you know is that it's a base class object, and attributes on member functions are part of that extra knowledge.
Reponses by Mike Miller of the C++ Core Working Group (3/30/2018).
I can't see any evidence in the C++17 wording that attributes are inherited by overriding functions.
The most relevant section I can find is the rules for overriding:
[class.virtual]/2:
If a virtual member functionvf
is declared in a classBase
and in a classDerived
, derived directly or indirectly fromBase
, a member functionvf
with the same name, parameter-type-list (11.3.5), cv-qualification, and ref-qualifier (or absence of same) asBase::vf
is declared, thenDerived::vf
is also virtual (whether or not it is so declared) and it overridesBase::vf
. [..]
While this passage attacks the problem from a slightly different angle, I think it's enough to show that only virtualness is "inherited" (and that attributes don't come into play at all when deciding whether one function overrides another). That being said, I think this is slightly underspecified and could do with a clarifying note at the very least.
Of course, this quickly gets complicated. Given the below example:
struct B {
[[nodiscard]] virtual bool foo() { return true; }
};
struct D : B {
bool foo() override { return false; }
};
int main() {
D().foo();
}
Clang will not issue a warning. However, access the function through a base pointer and it will.
struct B {
[[nodiscard]] virtual bool foo() { return true; }
};
struct D : B {
bool foo() override { return false; }
};
int main() {
D d;
((B*)&d)->foo();
}
What that means for your question, I'm not sure.
Again, I'd like to see a bit more guidance from the standard on this topic.
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