C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Not quite a template virtual function

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Wed, 02 Oct 2024 09:31:03 +0100
Even seeing the same functions in different order would be potentially ODR-breaking.

Overloading virtual functions is generally a bad idea, in the same ballpark as default arguments in virtual functions.

Virtual functions are first and foremost implementation customisation points. They have an interface, because you need to call them somehow, but if you need a more elaborate interface you can always do that with non-virtuals calling other virtual functions.

And there are CRTP patterns for providing ways for overriding multiple virtual functions in a convenient way.

On 2 October 2024 08:09:12 BST, "Robin Savonen Söderholm via Std-Proposals" <std-proposals_at_[hidden]> wrote:
>That example is potentially ODR breaking as you could have different
>compilation units that see different "SomeGlobalFunction":s
>
>// Robin
>
>On Wed, Oct 2, 2024, 08:05 Frederick Virchanza Gotham via Std-Proposals <
>std-proposals_at_[hidden]> wrote:
>
>> I respond to Arthur and Thiago in series below.
>>
>>
>> On Tue, Oct 1, 2024 at 4:50 PM Arthur O'Dwyer wrote:
>> >
>> > Since 'Act' is virtual, we cannot tell what it does with its `args`.
>> > For example, it might only care about the arity of the pack:
>> > class LightBlueMonkey : public BlueMonkey {
>> > int Act(auto&&... args) override { return sizeof...(args); }
>> > };
>> > or it might care about everything:
>> > class DarkBlueMonkey : public BlueMonkey {
>> > int Act(auto&&... args) override { (std::cout << ... << args);
>> return 0; }
>> > };
>>
>>
>> Those two examples don't count. While there are a finite number of
>> types to which you can apply "sizeof..." and "cout <<", it isn't a
>> small number. In a codebase such as Chromium I think it would be up in
>> the thousands.
>>
>> Let's take a more simple example:
>>
>> extern int SomeGlobalFunction(char );
>> extern bool SomeGlobalFunction(double);
>>
>> class Frog {
>> virtual decltype(auto) Act(auto&&... args) { return
>> SomeGlobalFunction( static_cast<decltype(args)>(args)... ); }
>> };
>>
>> When the compiler encounters the above code snippet, it could
>> transform the following line:
>>
>> virtual decltype(auto) Act(auto&&... args) { return
>> SomeGlobalFunction( static_cast<decltype(args)>(args)... ); }
>>
>> into two lines:
>>
>> virtual int Act(char const arg) { return SomeGlobalFunction(arg); }
>> virtual bool Act(double const arg) { return SomeGlobalFunction(arg);
>> }
>>
>> So the rule would be something like:
>>
>> "A class shall not have a non-static virtual method with the
>> parameter list "auto&&... args" unless the inline body of the method
>> contains an invocation of a non-template-and-non-variadic function
>> with the arguments "static_cast<decltype(args)>(args)..." -- in which
>> case the virtual method will be given an instantiation for each of the
>> overload signatures of the aforementioned
>> non-template-and-non-variadic function."
>>
>>
>> Thiago wrote:
>> >>
>> >> which means that 'Act' can really only have two possible signatures:
>> >>
>> >> double Act(int);
>> >> int Act(char, char, char);
>> >
>> > False.
>> > You can call Act(0U) thus creating an Act(unsigned)
>> > and that unsigned parameter is converted to int upon calling Do().
>>
>>
>> .................which is exactly the same as if you had called "Do"
>> giving it an "unsigned" instead of an "int". Hence why 'Act' can be
>> restricted to just two signatures.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>

Received on 2024-10-02 08:31:13