• Shouldn't there be a way to exclude member functions out of name lo

    From Jakob Bohm@21:1/5 to Johannes Gerd Becker on Wed Aug 12 13:00:41 2015
    On 02/08/2015 05:09, Johannes Gerd Becker wrote:


    Of course, defining a helper function outside the class is a workaround (=
    as
    is first defining a base class, as described in my original post).

    The point I would like to make, however, is another one.

    There are workarounds, yet they get the more tedious the more often the problem arises, namely in templated code. (To begin with: templates live mostly in headers, so the helper functions must live in headers as well,
    and break encapsulation, pollute my namespace or are simply inconvenient =
    as
    they have to be templates themselves).

    It seems consensus (more or less) now that non-member functions defined i=
    n
    the same namespace as a class are part of the interface of that class, BECAUSE they will usually be found by ADL.

    Now the rule that, within a member function of some class, say B, member functions of B take absolute precendence when a name is looked up, has th=
    e
    unwanted effect that some part of the interface of another, completely unrelated class A, namely the nonmember functions that belong to the interface of A, may become unusable from within B.

    Why can I write

    using namespace std;
    auto i = begin (vec);

    everywhere in my code, yet not within a class that has a member function named begin ()?

    I tempted to think this should be considered a design mistake.

    One could think of several approaches to solve that problem:

    1.) Introduce a clause like

    using explicit this;

    which would locally force explicitly using this-> when you want to access=
    a
    member. Then I would write

    using namespace std;
    using explicit this;
    auto i = begin (vec); // ADL
    auto j = this->begin (); // member

    2.) Introduce a special qualifier (like, e.g., .::) to indicate that the following name does *not* refer to a member function. Then I could write

    using namespace std;
    auto i = .::begin (vec); // ADL
    auto j = begin (); // member


    Doesn't the existing :: qualifier do this already:

    auto i == ::begin(vec); // ADL

    Or did I miss some unfortunate interaction with the way named namespaces
    were formally added to the language?


    Enjoy

    Jakob
    --
    Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
    Transformervej 29, 2860 S=C3=B8borg, Denmark. Direct +45 31 13 16 10
    This public discussion message is non-binding and may contain errors.
    WiseMo - Remote Service Management for PCs, Phones and Embedded


    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Johannes Gerd Becker@21:1/5 to All on Sun Aug 16 17:29:14 2015
    ...

    Why can I write

    using namespace std;
    auto i = begin (vec);

    everywhere in my code, yet not within a class that has a member function named begin ()?

    ...

    Doesn't the existing :: qualifier do this already:

    auto i == ::begin(vec); // ADL

    Or did I miss some unfortunate interaction with the way named namespaces
    were formally added to the language?


    Enjoy

    Jakob
    --
    Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
    Transformervej 29, 2860 S=C3=B8borg, Denmark. Direct +45 31 13 16 10
    This public discussion message is non-binding and may contain errors.
    WiseMo - Remote Service Management for PCs, Phones and Embedded

    No, it doesn't.

    ::begin is considered as a qualified id, and ADL is not done for qualified
    ids ([basic.lookup.argdep], paragraph 1). ::begin will always only refer to
    the global namespace ([basic.lookup.qual], paragraph 4).

    Best,
    Johannes


    --
    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Smith@21:1/5 to All on Thu Aug 20 01:10:12 2015
    On 27/07/15 18:22, Johannes Gerd Becker wrote:

    Currently, you cannot rely on ADL within a class defining a member
    function of the same name as the function you would like to be called.


    I must admit that my C++ is getting a bit rusty, but this "problem" was well-known a decade ago, typically manifesting with std::swap and member functions of the name. The solution then was equally well known, and
    continues to work in C++11/14:

    using std::begin;
    auto i = begin(c);

    Richard


    --
    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jakob Bohm@21:1/5 to Johannes Gerd Becker on Tue Aug 18 22:35:26 2015
    On 17/08/2015 01:29, Johannes Gerd Becker wrote:


    ...

    Why can I write

    using namespace std;
    auto i = begin (vec);

    everywhere in my code, yet not within a class that has a member functio=
    n
    named begin ()?

    ...


    Doesn't the existing :: qualifier do this already:

    auto i == ::begin(vec); // ADL

    Or did I miss some unfortunate interaction with the way named namespaces
    were formally added to the language?


    No, it doesn't.

    ::begin is considered as a qualified id, and ADL is not done for qualifie=
    d
    ids ([basic.lookup.argdep], paragraph 1). ::begin will always only refer =
    to
    the global namespace ([basic.lookup.qual], paragraph 4).


    Just to expand your statements for clarity, you seem to be saying two of
    the following three things:

    1. Qualified ids such as Foo::Bar(7, 'A') and ::Bar(7, 'A') are not
    looked up based on their argument types, thus greatly reducing the
    ability to invoke overloaded functions????

    2. Qualified ids such as Foo::Bar(7, 'A') and ::Bar(7, 'A') are not
    searched outside their specified scope/namespace, even if an outer
    scope/namespace provides a more appropriate overloaded function????

    3. The Global Scope prefix :: operator also excludes any non-class
    namespaces brought in via the using keyword, including the "std"
    namespace????

    #3 is the unfortunate interaction I alluded to in my previous post.

    If you are saying just #2 and #3, I am a bit confused what the original
    problem was:

    A. Unqualified ids such as Bar(7, 'A') are not searched beyond the
    first found scope containing an identifier Bar, even if that
    identifier has the wrong type for its arguments.

    B. Unqualified ids such as Bar(7, 'A') are not searched beyond the
    first found scope containing an identifier Bar, even if that
    identifier has the wrong type for its arguments, but only if that
    first found scope is a class declaration.

    C. Limitation A or B applies only to some language implementations or
    to some editions of the standard.

    In either case, I am still wondering why the exemplified issue cannot be handled directly with a Qualified Id, specifically which (2 or more) scopes
    do you want the template implementation to search for identifier begin().


    Enjoy

    Jakob
    --
    Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
    Transformervej 29, 2860 S=C3=B8borg, Denmark. Direct +45 31 13 16 10
    This public discussion message is non-binding and may contain errors.
    WiseMo - Remote Service Management for PCs, Phones and Embedded


    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Johannes Gerd Becker@21:1/5 to All on Fri Aug 21 19:14:21 2015
    Am Donnerstag, 20. August 2015 08:20:08 UTC+2 schrieb Richard Smith:
    On 27/07/15 18:22, Johannes Gerd Becker wrote:

    Currently, you cannot rely on ADL within a class defining a member
    function of the same name as the function you would like to be called.


    I must admit that my C++ is getting a bit rusty, but this "problem" was well-known a decade ago, typically manifesting with std::swap and member functions of the name. The solution then was equally well known, and continues to work in C++11/14:

    using std::begin;
    auto i = begin(c);

    Richard


    --
    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]


    That's definitely a very nice solution, which mitigates the problem a lot.

    Thank you very much for your most helpful posting.

    I still think being able to write

    using .::begin; // use non-member begin found by ADL
    auto i = begin (v);

    or

    auto i = .::begin (v);

    would be nice, as then I would not have to mention some begin in my code
    that is perhaps never used. Yet I do have to admit that the problem now has become more a cosmetic rather than a serious one.

    Best regards,
    Johannes


    --
    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)