Thread: Bjarne's member function binding sample is wrong?

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    1,579

    Bjarne's member function binding sample is wrong?

    Hello everyone,


    Here is the quoted section, words from Bjarne and his sample. The reason why I think the sample is wrong, is because, the member function sort accepts empty arguments, so when we call ::sort (v), only the one in global namespace will be matched -- there is no ambiguity to call sort member function of Container from parameter list comparison. I do not know why Bjarne commets "sort (vector<T>&) which calls std::sort() rather than Container::sort()" -- I think it has nothing to do with template -- just a normal function call matching.

    Any comments? Do you agree with me and think his sample is wrong?

    section 13.8.3 Point of Instantiation Binding

    --------------------
    unqualified name can not be bound to members of that class
    --------------------

    Code:
    template <class T> void sort (vector<T>& v)
    {
    	sort (v.begin(), v.end());
    }
    
    class Container {
    	vector<int> v; // elements
    public:
    	void sort() // sort elements
    	{
    		::sort (v); // sort (vector<T>&) which calls std::sort() rather than Container::sort()
    	}
    };

    thanks in advance,
    George

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    George, I do not agree. Remove the scoping operator from the call. This is completely different: Because we are inside the class' scope, the compiler will think you want to call Container::sort recursively. Because Container::sort doesn't take an argument, the compiler will stop and issue an error.

    So scoping is necessary if you intend to call the global sort (vector<T> &) instead of Container::sort. Bjarne's comment is correct.
    Last edited by whiteflags; 03-09-2008 at 09:58 PM.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi citizen,


    I have tried when removing :: qualifier, there is a compile error,

    error C2660: 'Container::sort' : function does not take 1 arguments

    I think the rule is simlpe, if :: qualified, looking for global names, if not, looking for class wide names. It is general to all name findings, no special to template name binding.

    I am not sure what is Bjarne's purpose of using this sample to express his idea of,

    section 13.8.3 Point of Instantiation Binding

    --------------------
    unqualified name can not be bound to members of that class
    --------------------

    Any comments and ideas?

    Quote Originally Posted by citizen View Post
    George, I do not agree. Remove the scoping operator from the call. This is completely different: Because we are inside the class' scope, the compiler will think you want to call Container::sort recursively. Because Container::sort doesn't take an argument, the compiler will stop and issue an error.

    So scoping is necessary if you intend to call the global sort (vector<T> &) instead of Container::sort. Bjarne's comment is correct.

    regards,
    George

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Look at it this way: in Container::sort(), you explicitly qualify the call to ::sort(vector<T>), because otherwise it would find Container::sort() and complain that the arguments don't match, as you've seen when you removed the explicit scoping operator.

    Now, the PoI for ::sort(vector<T>) could be assumed to be just before the function where it's used - that is, just before Container::sort(). A naive view of the situation would therefore be that the unqualified sort call in ::sort(vector<T>) would follow the same name binding rules as Container::sort(). In other words, the call to sort(begin, end) would find Container::sort() and error out because the arguments don't match.

    However, the PoI is not before the function. The PoI is before the function at the nearest global/namespace scope. In this case, the PoI is just before the definition of class Container. Thus, the names cannot bind to class-local elements and sanity is restored.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks CornedBee,


    Two more comments,

    1.

    Quote Originally Posted by CornedBee View Post
    In other words, the call to sort(begin, end) would find Container::sort() and error out because the arguments don't match.
    I do not agree sort (begin, end) call in global sort function will call sort member function in class Conatiner. How could a global function call a member function directly in a class without through the class object instance?

    2.

    Quote Originally Posted by CornedBee View Post
    However, the PoI is not before the function. The PoI is before the function at the nearest global/namespace scope. In this case, the PoI is just before the definition of class Container. Thus, the names cannot bind to class-local elements and sanity is restored.
    Does your quoted statements reflects Bjarne's comments below?

    section 13.8.3 Point of Instantiation Binding

    --------------------
    unqualified name can not be bound to members of that class
    --------------------

    What is "qualified name" reflected in the sample code in your description? What is the "member of class" relected in the sample code in your description?


    regards,
    George

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    1)
    I do not agree sort (begin, end) call in global sort function will call sort member function in class Conatiner.
    It doesn't. But were the PoI rules different, it might. That's the whole point of Bjarne's comment.

    2) My statement is the reason for the fact described by Bjarne's statement.
    I don't understand your other two questions.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks CornedBee,


    I think if you mean inside the global sort function, it can not call member function sort of Container class, it is nonsenses, since it breaks the basic C++ rule -- how could you invoke a member function of the class but not through class instance name/pointer name/class name?

    Any comments and what do you think are Bjarne's points?

    As a reference I post all the content of the chapter here.

    C.13.8.3 Point of Instantiation Binding
    Each use of a template for a given set of template arguments defines a point of instantiation. That
    point is in the nearest global or namespace scope enclosing its use, just before the declaration that
    contains that use. For example:

    Code:
    t e m p l a t e <c l a s s T > v o i d f (T a ) { g (a ); }
    v o i d g (i n t );
    v o i d h ()
    {
    e x t e r n g (d o u b l e );
    f(2) ;
    }
    Here, the point of instantiation for f <i n t >() is just before h (), so the g () called in f () is the global
    g (i n t ) rather than the local g (d o u b l e ). The definition of ‘‘instantiation point’’ implies that a
    template parameter can never be bound to a local name or a class member. For example:

    Code:
    v o i d f ()
    {
    s t r u c t X { /* ... */ }; // local structure
    v e c t o r <X > v ; // error: cannot use local structure as template parameter
    / / ...
    }
    Nor can an unqualified name used in a template ever be bound to a local name. Finally, even if a
    template is first used within a class, unqualified names used in the template will not be bound to
    members of that class. Ignoring local names is essential to prevent a lot of nasty macrolike
    behavior.
    For example:

    Code:
    t e m p l a t e <c l a s s T > v o i d s o r t (v e c t o r <T >& v )
    {
    s o r t (v .b e g i n (), v .e n d ()); // use standard library sort()
    }
    c l a s s C o n t a i n e r {
    v e c t o r <i n t > v ; // elements
    / / ...
    p u b l i c :
    v o i d s o r t () // sort elements
    {
    s o r t (v ); // invokes sort(vectorint&) rather than Container::sort()
    }
    / / ...
    };
    If the point of instantiation for a template defined in a namespace is in another namespace, names
    from both namespaces are available for name binding. As always, overload resolution is used to
    choose between names from different namespaces (§8.2.9.2).
    Note that a template used several times with the same set of template arguments has several
    points of instantiation. If the bindings of independent names differ, the program is illegal. However,
    this is a difficult error for an implementation to detect, especially if the points of instantiation
    are in different translation units. It is best to avoid subtleties in name binding by minimizing the
    use of nonlocal names in templates and by using header files to keep use contexts consistent.

    Quote Originally Posted by CornedBee View Post
    1)
    It doesn't. But were the PoI rules different, it might. That's the whole point of Bjarne's comment.

    regards,
    George

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Just forget Bjarne said anything. His comment is there to preempt a possible misunderstanding readers might have. Since you don't have that misunderstanding, but instead are confused by his comment, just ignore it.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks CornedBee,


    You mean some readers will think the following call

    Code:
    sort (v.begin (), v.end ()); // use standard library sort()
    invokes sort member function Container? It is unbelievable to find someone will think we can call a member function of a class without through from instance handle, and call directly.

    Quote Originally Posted by CornedBee View Post
    Just forget Bjarne said anything. His comment is there to preempt a possible misunderstanding readers might have. Since you don't have that misunderstanding, but instead are confused by his comment, just ignore it.

    regards,
    George

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Not at all unbelievable. If you take earlier statements in the section the wrong way, that's exactly what you might believe.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. Calling a Thread with a Function Pointer.
    By ScrollMaster in forum Windows Programming
    Replies: 6
    Last Post: 06-10-2006, 08:56 AM
  4. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  5. Menu Item Caption - /a for right aligned Accelerator?
    By JasonD in forum Windows Programming
    Replies: 6
    Last Post: 06-25-2003, 11:14 AM