C++ Logo

std-discussion

Advanced search

Re: [std-proposals] Should every declaration that using-declarator declared should be accessible?

From: chuanqi.xcq <yedeng.yd_at_[hidden]>
Date: Tue, 29 Jun 2021 10:22:59 +0800
Hi Artuhr,

> Class `A` has overloaded public and private constructors, and overloaded public and private `get` methods.
> Class `B` can say `using A::A;` just fine. But it can't say `using A::get;`. This feels inconsistent.

Yeah, it's my main point. It looks inconsistent.

> In Chuanqi's specific case, the right refactoring is not to use `using` — I mean, to a first approximation, using `using` is never appropriate in modern C++!

May I ask what's the reason to refuse ** using **? It's my first time to hear it.

> The right refactoring is to eliminate the combination of overloading and virtual methods. Virtual methods aren't called directly by the client (because Non-Virtual Interface Idiom), so you're in control of these names, so you can > give them whatever names you choose. For example, "virtual void *getByName(char *)" and "virtual void *getByNameAndIndex(char *, int)". Then the names don't collide, so there's no name hiding, so you don't have to work > around anything at all.

It looks like we could only do more aggressive refactoring. OK, maybe it's the right solution even it is harder.

> See also "When Should You Give Two Things the Same Name?" (CppCon 2021), which coincidentally "premieres in 3 hours from now" according to YouTube.

Thanks for sharing!

---
Finally, I want to discuss that if the control of `using` is too coarsed grained.
Since `using A::foo` declares all of names foo in A. 
But what if we want to declare only one of them? 
I understand people may argue that the user should rewrite the code to avoid same name problem.
However, I think that member functions with the same name is fine due to the existence of overloading.
Then the ability to declare one of the functions would be beneficial in that case.
The grammer may be:
```
using A::foo(int, int);
```
Thanks,
Chuanqi
------------------------------------------------------------------
From:Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Send Time:2021年6月28日(星期一) 22:17
To:Std-Proposals <std-proposals_at_[hidden]>
Cc:std-discussion <std-discussion_at_[hidden]>; chuanqi.xcq <yedeng.yd_at_[hidden]>
Subject:Re: [std-proposals] Should every declaration that using-declarator declared should be accessible?
On Mon, Jun 28, 2021 at 3:26 AM chuanqi.xcq via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> I am cleanning some codes with the warning of overloaded virtual functions.
> Here is the introduction for overloaded virtual functions:
> https://stackoverflow.com/questions/18515183/c-overloaded-virtual-function-warning-by-clang
[...]
> At first, I thought it is a compiler bug.
> However, I find these words in 9.9.14 N4878,
> "In a using-declarator that does not name a constructor, every declaration named shall be accessible."
It took me a while to understand your example. Eventually I got it:
https://godbolt.org/z/M3fhPxhjc
Class `A` has overloaded public and private constructors, and overloaded public and private `get` methods.
Class `B` can say `using A::A;` just fine. But it can't say `using A::get;`. This feels inconsistent.
However, `using A::A` does something very different from `using A::get`. When you inherit constructors with `using`, you're doing it because constructors are not ordinarily inherited at all. When you `using` the name of an ordinary member function, it's not "to inherit them," because ordinary member functions are already inherited just fine; it's rather because you want to change the access control of the existing names.
https://godbolt.org/z/cM3PPjKaK
In Chuanqi's specific case, the right refactoring is not to use `using` — I mean, to a first approximation, using `using` is never appropriate in modern C++! The right refactoring is to eliminate the combination of overloading and virtual methods. Virtual methods aren't called directly by the client (because Non-Virtual Interface Idiom), so you're in control of these names, so you can give them whatever names you choose.  For example, "virtual void *getByName(char *)" and "virtual void *getByNameAndIndex(char *, int)". Then the names don't collide, so there's no name hiding, so you don't have to work around anything at all.
See also "When Should You Give Two Things the Same Name?" (CppCon 2021), which coincidentally "premieres in 3 hours from now" according to YouTube.
HTH,
Arthur

Received on 2021-06-28 21:23:13