Why doesn't the default argument allow const member?

Discussion in 'C++' started by Divick, Sep 21, 2009.

  1. Divick

    Divick Guest

    Hi,

    I have the following code (see below). My compiler g++ 3.4.6 doesn't
    compile it. I wonder why shouldn't this be allowed? I understand that
    const int a, would be different for different objects, unlike static
    const. And functions are common for all objects. But from the
    compiler's perspective, shouldn't it be simple to handle as for every
    invocation of a function with default argument, if the value is not
    supplied then the compiler can simply initialize the function with the
    value on which the function has been called?

    class x
    {
    private :
    const int a;
    public :
    X() : a(1)
    {}

    void foo(int arg = a)
    {
    cout << arg << endl;
    }

    };

    Thanks in advance,
    -DK
     
    Divick, Sep 21, 2009
    #1
    1. Advertising

  2. Divick

    Thomas Lenz Guest

    Divick wrote:

    > Hi,
    >
    > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > compile it. I wonder why shouldn't this be allowed? I understand that
    > const int a, would be different for different objects, unlike static
    > const. And functions are common for all objects. But from the
    > compiler's perspective, shouldn't it be simple to handle as for every
    > invocation of a function with default argument, if the value is not
    > supplied then the compiler can simply initialize the function with the
    > value on which the function has been called?
    >
    > class x
    > {
    > private :
    > const int a;
    > public :
    > X() : a(1)
    > {}
    >
    > void foo(int arg = a)
    > {
    > cout << arg << endl;
    > }
    >
    > };
    >
    > Thanks in advance,
    > -DK


    Is it just a typo, or is your class name x but your Ctor (capital) X ?
     
    Thomas Lenz, Sep 21, 2009
    #2
    1. Advertising

  3. On 21 Set, 11:53, Divick <> wrote:
    > Hi,
    >
    > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > compile it. I wonder why shouldn't this be allowed? I understand that
    > const int a, would be different for different objects, unlike static
    > const. And functions are common for all objects. But from the
    > compiler's perspective, shouldn't it be simple to handle as for every
    > invocation of a function with default argument, if the value is not
    > supplied then the compiler can simply initialize the function with the
    > value on which the function has been called?
    >
    > class x
    > {
    > private :
    > const int a;
    > public :
    > X() : a(1)
    > {}
    >
    > void foo(int arg = a)
    > {
    > cout << arg << endl;
    > }
    >
    > };
    >
    > Thanks in advance,
    > -DK


    If I got it right, members functions aren't much different from normal
    functions, that is, you should think of your "foo(int)" as something
    like "foo(int, A* this)", because the function itself is not aware of
    the object it is called upon and needs the "hidden 'this' argument" to
    be aware of it.

    Unfortunately you cannot even write something like "void foo(int arg =
    this->a)", because the 'this' pointer is visible only inside of the
    function's body.

    If you need a workaround, one way could be to decide a range of values
    that lead to use the const value, such as:
    -------
    class A {
    const int i;
    public:
    A(int v = 0) : i(v) {}
    int foo(int v = -1) {
    if(v < 0) {
    return i;
    } else {
    return v;
    }
    }
    };
    -------

    For what is worth, hope that helps.

    Have good time,
    Francesco
    --
    Francesco S. Carta, hobbyist
    http://fscode.altervista.org
     
    Francesco S. Carta, Sep 21, 2009
    #3
  4. Divick

    Ron Guest

    On Sep 21, 5:53 am, Divick <> wrote:
    > Hi,
    >
    > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > compile it. I wonder why shouldn't this be allowed?


    It's not allowed. The default arg substitution is done by the
    caller.
     
    Ron, Sep 21, 2009
    #4
  5. Divick

    Bo Persson Guest

    Divick wrote:
    > Hi,
    >
    > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > compile it. I wonder why shouldn't this be allowed? I understand
    > that const int a, would be different for different objects, unlike
    > static const. And functions are common for all objects. But from the
    > compiler's perspective, shouldn't it be simple to handle as for
    > every invocation of a function with default argument, if the value
    > is not supplied then the compiler can simply initialize the
    > function with the value on which the function has been called?
    >
    > class x
    > {
    > private :
    > const int a;
    > public :
    > X() : a(1)
    > {}
    >
    > void foo(int arg = a)
    > {
    > cout << arg << endl;
    > }
    >
    > };
    >


    It is not actually a bad idea, however it is expressly forbidden by
    the standard. Default arguments cannot use non-static members, or the
    keyword 'this'.

    If you make a static it will work, but of course share its value
    between all x objects.


    As a workaround, you can add an overload that gets the correct value:

    void foo()
    {
    foo(a);
    }


    Bo Persson
     
    Bo Persson, Sep 21, 2009
    #5
  6. On 21 Set, 20:22, "Bo Persson" <> wrote:
    > Divick wrote:
    > > Hi,

    >
    > > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > > compile it. I wonder why shouldn't this be allowed? I understand
    > > that const int a, would be different for different objects, unlike
    > > static const. And functions are common for all objects. But from the
    > > compiler's perspective, shouldn't it be simple to handle as for
    > > every invocation of a function with default argument, if the value
    > > is not supplied then the compiler can simply initialize the
    > > function with the value on which the function has been called?

    >
    > > class x
    > > {
    > > private :
    > >       const int a;
    > > public :
    > >       X() : a(1)
    > >       {}

    >
    > >       void foo(int arg = a)
    > >       {
    > >               cout << arg << endl;
    > >       }

    >
    > > };

    >
    > It is not actually a bad idea, however it is expressly forbidden by
    > the standard. Default arguments cannot use non-static members, or the
    > keyword 'this'.
    >
    > If you make a static it will work, but of course share its value
    > between all x objects.
    >
    > As a workaround, you can add an overload that gets the correct value:
    >
    >      void foo()
    >      {
    >           foo(a);
    >      }


    Which is way better than my proposition, thanks for pointing this out
    Bo.

    Have good time,
    Francesco
    --
    Francesco S. Carta, hobbyist
    http://fscode.altervista.org
     
    Francesco S. Carta, Sep 21, 2009
    #6
  7. Divick

    Divick Guest

    On Sep 21, 11:22 pm, "Bo Persson" <> wrote:
    > Divick wrote:
    > > Hi,

    >
    > > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > > compile it. I wonder why shouldn't this be allowed? I understand
    > > that const int a, would be different for different objects, unlike
    > > static const. And functions are common for all objects. But from the
    > > compiler's perspective, shouldn't it be simple to handle as for
    > > every invocation of a function with default argument, if the value
    > > is not supplied then the compiler can simply initialize the
    > > function with the value on which the function has been called?

    >
    > > class x
    > > {
    > > private :
    > >       const int a;
    > > public :
    > >       X() : a(1)
    > >       {}

    >
    > >       void foo(int arg = a)
    > >       {
    > >               cout << arg << endl;
    > >       }

    >
    > > };

    >
    > It is not actually a bad idea, however it is expressly forbidden by
    > the standard. Default arguments cannot use non-static members, or the
    > keyword 'this'.
    >
    > If you make a static it will work, but of course share its value
    > between all x objects.
    >
    > As a workaround, you can add an overload that gets the correct value:
    >
    >      void foo()
    >      {
    >           foo(a);
    >      }
    >
    > Bo Persson


    I think I could guess that it is not allowed by the standard, but my
    question was originally about why it is not allowed. Unless there is a
    good reason for disallowing it in the standard, the standard could
    have allowed non static default argument as well.

    Thanks for the replies,
    DK
     
    Divick, Sep 22, 2009
    #7
  8. Divick

    Divick Guest

    On Sep 21, 5:14 pm, Ron <> wrote:
    > On Sep 21, 5:53 am, Divick <> wrote:
    >
    > > Hi,

    >
    > > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > > compile it. I wonder why shouldn't this be allowed?

    >
    > It's not allowed.   The default arg substitution is done by the
    > caller.


    The question is why is it not allowed? As long as arguments are known
    at compile time, the compiler could easily substitute the default
    argument be it static or non static.

    Thanks for the reply,
    DK
     
    Divick, Sep 22, 2009
    #8
  9. On Sep 22, 10:18 am, Divick <> wrote:
    > On Sep 21, 5:14 pm, Ron <> wrote:
    >
    > > On Sep 21, 5:53 am, Divick <> wrote:

    >
    > > > Hi,

    >
    > > > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > > > compile it. I wonder why shouldn't this be allowed?

    >
    > > It's not allowed.   The default arg substitution is done by the
    > > caller.

    >
    > The question is why is it not allowed? As long as arguments are known
    > at compile time, the compiler could easily substitute the default
    > argument be it static or non static.


    Really?
    How does the compiler know what to substitute in these lines:

    int main()
    {
    x foo, bar;
    foo.foo();
    bar.foo();
    }

    Remember that the default argument 'a' must be accessible from the
    context of main().

    >
    > Thanks for the reply,
    > DK


    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Sep 22, 2009
    #9
  10. Divick

    Fred Zwarts Guest

    >"Bart van Ingen Schenau" <> wrote in message news:...
    >On Sep 22, 10:18 am, Divick <> wrote:
    >> On Sep 21, 5:14 pm, Ron <> wrote:
    >>
    >> > On Sep 21, 5:53 am, Divick <> wrote:

    >>
    >> > > Hi,

    >>
    >> > > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    >> > > compile it. I wonder why shouldn't this be allowed?

    >>
    >> > It's not allowed. The default arg substitution is done by the
    >> > caller.

    >>
    >> The question is why is it not allowed? As long as arguments are known
    >> at compile time, the compiler could easily substitute the default
    >> argument be it static or non static.

    >
    >Really?
    >How does the compiler know what to substitute in these lines:
    >
    >int main()
    >{
    >x foo, bar;
    >foo.foo();
    >bar.foo();
    >}
    >
    >Remember that the default argument 'a' must be accessible from the
    >context of main().


    Could you elaborate?
    If the non-static member function "foo ()" of "x" is accessible by the compiler from the context of main (),
    it means that the declaration of "x" is within the context of main.
    The declaration of "x" includes the default parameter value "a" for the function "foo ()".
    Why then should the non-static member "a" of "x" be inaccessible by the compiler from the context of main?
     
    Fred Zwarts, Sep 22, 2009
    #10
  11. Divick

    Bo Persson Guest

    Divick wrote:
    > On Sep 21, 11:22 pm, "Bo Persson" <> wrote:
    >> Divick wrote:
    >>> Hi,

    >>
    >>> I have the following code (see below). My compiler g++ 3.4.6
    >>> doesn't compile it. I wonder why shouldn't this be allowed? I
    >>> understand that const int a, would be different for different
    >>> objects, unlike static const. And functions are common for all
    >>> objects. But from the compiler's perspective, shouldn't it be
    >>> simple to handle as for every invocation of a function with
    >>> default argument, if the value is not supplied then the compiler
    >>> can simply initialize the function with the value on which the
    >>> function has been called?

    >>
    >>> class x
    >>> {
    >>> private :
    >>> const int a;
    >>> public :
    >>> X() : a(1)
    >>> {}

    >>
    >>> void foo(int arg = a)
    >>> {
    >>> cout << arg << endl;
    >>> }

    >>
    >>> };

    >>
    >> It is not actually a bad idea, however it is expressly forbidden by
    >> the standard. Default arguments cannot use non-static members, or
    >> the keyword 'this'.
    >>
    >> If you make a static it will work, but of course share its value
    >> between all x objects.
    >>
    >> As a workaround, you can add an overload that gets the correct
    >> value:
    >>
    >> void foo()
    >> {
    >> foo(a);
    >> }
    >>
    >> Bo Persson

    >
    > I think I could guess that it is not allowed by the standard, but my
    > question was originally about why it is not allowed. Unless there
    > is a good reason for disallowing it in the standard, the standard
    > could have allowed non static default argument as well.
    >


    The standard usually doesn't give any reason for the rules, it just
    states what they are.

    In this case, I agree that it would be feasible for the caller to
    supply not only the 'this' pointer, but also 'this->a' as a parameter
    value (with the exception that as a is private, it is a bit
    questionable if it should :).

    I can only imagine that as the 'this' pointer is formally provided by
    magic inside the member function, perhaps we cannot require that the
    caller knows what it is, so in theory there are cases where it cannot
    provide this->a.


    Bo Perssob
     
    Bo Persson, Sep 22, 2009
    #11
  12. On Sep 22, 2:28 pm, "Fred Zwarts" <> wrote:
    > >"Bart van Ingen Schenau" <> wrote in messagenews:...
    > >On Sep 22, 10:18 am, Divick <> wrote:
    > >> On Sep 21, 5:14 pm, Ron <> wrote:

    >
    > >> > On Sep 21, 5:53 am, Divick <> wrote:

    >
    > >> > > Hi,

    >
    > >> > > I have the following code (see below). My compiler g++ 3.4.6 doesn't
    > >> > > compile it. I wonder why shouldn't this be allowed?

    >
    > >> > It's not allowed. The default arg substitution is done by the
    > >> > caller.

    >
    > >> The question is why is it not allowed? As long as arguments are known
    > >> at compile time, the compiler could easily substitute the default
    > >> argument be it static or non static.

    >
    > >Really?
    > >How does the compiler know what to substitute in these lines:

    >
    > >int main()
    > >{
    > >x foo, bar;
    > >foo.foo();
    > >bar.foo();
    > >}

    >
    > >Remember that the default argument 'a' must be accessible from the
    > >context of main().

    >
    > Could you elaborate?
    > If the non-static member function "foo ()" of "x" is accessible by the compiler from the context of main (),


    It isn't. The name of the member function is only looked up within the
    scope of class x. In this case, the compiler knows to look in the
    class x due to the use of the member-access operator (operator.) on an
    object of type x.

    > it means that the declaration of "x" is within the context of main.
    > The declaration of "x" includes the default parameter value "a" for the function "foo ()".
    > Why then should the non-static member "a" of "x" be inaccessible by the compiler from the context of main?


    Lets put it in another way. The main function above is semantically
    equivalent to this one:

    int main()
    {
    x foo, bar;
    foo.foo(a);
    bar.foo(a);
    }

    Which 'a' am I referring top here?

    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Sep 23, 2009
    #12
  13. Divick

    Fred Zwarts Guest

    >"Bart van Ingen Schenau" <> wrote in message news:...
    >
    > ...
    >
    >Lets put it in another way. The main function above is semantically
    >equivalent to this one:
    >
    > int main()
    > {
    > x foo, bar;
    > foo.foo(a);
    > bar.foo(a);
    > }


    The C++ standard does not allow it, so it is speculation what the sematically equivalent would be if it would allow it.
    I assume if the C++ standard would allow it, the semantically equivalent would be:

    int main ()
    {
    x foo, bar;
    foo.foo(foo.a);
    bar.foo(bar.a);
    }

    I see no reason why this could not be defined as such.
    All the information needed by the compiler for this interpretation is available.

    > Which 'a' am I referring top here?


    This question is then no longer relevant.
     
    Fred Zwarts, Sep 23, 2009
    #13
  14. Divick

    Balog Pal Guest

    "Fred Zwarts" <>

    >>Lets put it in another way. The main function above is semantically
    >>equivalent to this one:
    >>
    >> int main()
    >> {
    >> x foo, bar;
    >> foo.foo(a);
    >> bar.foo(a);
    >> }


    >The C++ standard does not allow it, so it is speculation what the
    >sematically >equivalent would be if it would allow it.
    >I assume if the C++ standard would allow it, the semantically equivalent
    >would >be:


    >int main ()
    >{
    >x foo, bar;
    >foo.foo(foo.a);
    >bar.foo(bar.a);
    >}


    Hardly. The context of name lookup at that spot is clearly that of the
    function block, and going outside to namespaces. foo and bar only
    influences the picture through ADL, but that will not pick any names from
    inside foo's type either.
    I.e. if you have

    struct x { enum e { v1, v2, v3 }; void f(e); } ;
    int main () {
    x foo;
    foo.f(v1); // not good
    foo.f(x::v1); //qualification needed!
    }

    At the spot if you want anything from inside, you must say so. Certainly if
    you are definig a member function, the situation is different.
     
    Balog Pal, Sep 23, 2009
    #14
  15. Divick

    Divick Guest

    On Sep 23, 12:17 am, "Bo Persson" <> wrote:
    > Divick wrote:
    > > On Sep 21, 11:22 pm, "Bo Persson" <> wrote:
    > >> Divick wrote:
    > >>> Hi,

    >
    > >>> I have the following code (see below). My compiler g++ 3.4.6
    > >>> doesn't compile it. I wonder why shouldn't this be allowed? I
    > >>> understand that const int a, would be different for different
    > >>> objects, unlike static const. And functions are common for all
    > >>> objects. But from the compiler's perspective, shouldn't it be
    > >>> simple to handle as for every invocation of a function with
    > >>> default argument, if the value is not supplied then the compiler
    > >>> can simply initialize the function with the value on which the
    > >>> function has been called?

    >
    > >>> class x
    > >>> {
    > >>> private :
    > >>> const int a;
    > >>> public :
    > >>> X() : a(1)
    > >>> {}

    >
    > >>> void foo(int arg = a)
    > >>> {
    > >>> cout << arg << endl;
    > >>> }

    >
    > >>> };

    >
    > >> It is not actually a bad idea, however it is expressly forbidden by
    > >> the standard. Default arguments cannot use non-static members, or
    > >> the keyword 'this'.

    >
    > >> If you make a static it will work, but of course share its value
    > >> between all x objects.

    >
    > >> As a workaround, you can add an overload that gets the correct
    > >> value:

    >
    > >> void foo()
    > >> {
    > >> foo(a);
    > >> }

    >
    > >> Bo Persson

    >
    > > I think I could guess that it is not allowed by the standard, but my
    > > question was originally about why it is not allowed. Unless there
    > > is a good reason for disallowing it in the standard, the standard
    > > could have allowed non static default argument as well.

    >
    > The standard usually doesn't give any reason for the rules, it just
    > states what they are.
    >
    > In this case, I agree that it would be feasible for the caller to
    > supply not only the 'this' pointer, but also 'this->a' as a parameter
    > value (with the exception that as a is private, it is a bit
    > questionable if it should :).
    >
    > I can only imagine that as the 'this' pointer is formally provided by
    > magic inside the member function, perhaps we cannot require that the
    > caller knows what it is, so in theory there are cases where it cannot
    > provide this->a.
    >
    > Bo Perssob


    Could you post some example /cases where it doesn't know what this->a
    is? In earlier post by Bart, he points to the fact that variable a is
    inaccessible in the scope of main because it is private. But here we
    are not talking about visibility at the language level but visibility
    at the compiler level. Compiler does have knowledge / visibility of
    this->a, while in the context of language / scope, surely the variable
    is not accessible. I would assume that default arguments are something
    that are dealt by the compiler and during the runtime.
     
    Divick, Sep 23, 2009
    #15
  16. Divick

    Divick Guest

    On Sep 23, 4:42 pm, "Fred Zwarts" <> wrote:
    > >"Bart van Ingen Schenau" <> wrote in messagenews:...

    >
    > > ...

    >
    > >Lets put it in another way. The main function above is semantically
    > >equivalent to this one:

    >
    > > int main()
    > > {
    > > x foo, bar;
    > > foo.foo(a);
    > > bar.foo(a);
    > > }

    >
    > The C++ standard does not allow it, so it is speculation what the sematically equivalent would be if it would allow it.
    > I assume if the C++ standard would allow it, the semantically equivalent would be:
    >
    > int main ()
    > {
    > x foo, bar;
    > foo.foo(foo.a);
    > bar.foo(bar.a);
    >
    > }
    >
    > I see no reason why this could not be defined as such.
    > All the information needed by the compiler for this interpretation is available.
    >
    > > Which 'a' am I referring top here?

    >
    > This question is then no longer relevant.


    Having looked at the various posts, I feel that this discussion is
    still inconclusive and I would agree with Fred that it is simply not
    allowed by the standard, probably to ease the job of compiler writer.

    I think the other angle to look at this problem can be from a
    perspective of multi-threading. I am not aware if language designers
    keep multi threading issues while designing languages or not, but it
    appears that default argument with non static member variable could be
    an issue in multi-threading environments. For example on a multi
    processor system if one thread is writing to the variable and the
    other one is reading the same variable to be passed as default
    argument, without being protected by a lock, it can lead to different
    behaviors / data passed based on who reads / writes first. But if the
    programmer is aware of this issue then from a language design
    perspective I guess it is not an issue.

    Does anyone have any ideas, thoughts if this could be the reason?

    Thanks to all for the earlier replies,
    DK
     
    Divick, Sep 23, 2009
    #16
  17. Divick

    Divick Guest

    On Sep 23, 6:36 pm, Divick <> wrote:
    > On Sep 23, 12:17 am, "Bo Persson" <> wrote:
    >
    >
    >
    > > Divick wrote:
    > > > On Sep 21, 11:22 pm, "Bo Persson" <> wrote:
    > > >> Divick wrote:
    > > >>> Hi,

    >
    > > >>> I have the following code (see below). My compiler g++ 3.4.6
    > > >>> doesn't compile it. I wonder why shouldn't this be allowed? I
    > > >>> understand that const int a, would be different for different
    > > >>> objects, unlike static const. And functions are common for all
    > > >>> objects. But from the compiler's perspective, shouldn't it be
    > > >>> simple to handle as for every invocation of a function with
    > > >>> default argument, if the value is not supplied then the compiler
    > > >>> can simply initialize the function with the value on which the
    > > >>> function has been called?

    >
    > > >>> class x
    > > >>> {
    > > >>> private :
    > > >>> const int a;
    > > >>> public :
    > > >>> X() : a(1)
    > > >>> {}

    >
    > > >>> void foo(int arg = a)
    > > >>> {
    > > >>> cout << arg << endl;
    > > >>> }

    >
    > > >>> };

    >
    > > >> It is not actually a bad idea, however it is expressly forbidden by
    > > >> the standard. Default arguments cannot use non-static members, or
    > > >> the keyword 'this'.

    >
    > > >> If you make a static it will work, but of course share its value
    > > >> between all x objects.

    >
    > > >> As a workaround, you can add an overload that gets the correct
    > > >> value:

    >
    > > >> void foo()
    > > >> {
    > > >> foo(a);
    > > >> }

    >
    > > >> Bo Persson

    >
    > > > I think I could guess that it is not allowed by the standard, but my
    > > > question was originally about why it is not allowed. Unless there
    > > > is a good reason for disallowing it in the standard, the standard
    > > > could have allowed non static default argument as well.

    >
    > > The standard usually doesn't give any reason for the rules, it just
    > > states what they are.

    >
    > > In this case, I agree that it would be feasible for the caller to
    > > supply not only the 'this' pointer, but also 'this->a' as a parameter
    > > value (with the exception that as a is private, it is a bit
    > > questionable if it should :).

    >
    > > I can only imagine that as the 'this' pointer is formally provided by
    > > magic inside the member function, perhaps we cannot require that the
    > > caller knows what it is, so in theory there are cases where it cannot
    > > provide this->a.

    >
    > > Bo Perssob

    >
    > Could you post some example /cases where it doesn't know what this->a
    > is? In earlier post by Bart, he points to the fact that variable a is
    > inaccessible in the scope of main because it is private. But here we
    > are not talking about visibility at the language level but visibility
    > at the compiler level. Compiler does have knowledge / visibility of
    > this->a, while in the context of language / scope, surely the variable
    > is not accessible. I would assume that default arguments are something
    > that are dealt by the compiler and during the runtime.


    Please read that last line as

    I would assume that default arguments are something that are dealt by
    the compiler and NOT during the runtime.
     
    Divick, Sep 23, 2009
    #17
  18. Divick

    Bo Persson Guest

    Divick wrote:
    > On Sep 23, 6:36 pm, Divick <> wrote:
    >> On Sep 23, 12:17 am, "Bo Persson" <> wrote:
    >>
    >>
    >>
    >>> Divick wrote:
    >>>> On Sep 21, 11:22 pm, "Bo Persson" <> wrote:
    >>>>> Divick wrote:
    >>>>>> Hi,

    >>
    >>>>>> I have the following code (see below). My compiler g++ 3.4.6
    >>>>>> doesn't compile it. I wonder why shouldn't this be allowed? I
    >>>>>> understand that const int a, would be different for different
    >>>>>> objects, unlike static const. And functions are common for all
    >>>>>> objects. But from the compiler's perspective, shouldn't it be
    >>>>>> simple to handle as for every invocation of a function with
    >>>>>> default argument, if the value is not supplied then the
    >>>>>> compiler can simply initialize the function with the value on
    >>>>>> which the function has been called?

    >>
    >>>>>> class x
    >>>>>> {
    >>>>>> private :
    >>>>>> const int a;
    >>>>>> public :
    >>>>>> X() : a(1)
    >>>>>> {}

    >>
    >>>>>> void foo(int arg = a)
    >>>>>> {
    >>>>>> cout << arg << endl;
    >>>>>> }

    >>
    >>>>>> };

    >>
    >>>>> It is not actually a bad idea, however it is expressly
    >>>>> forbidden by the standard. Default arguments cannot use
    >>>>> non-static members, or the keyword 'this'.

    >>
    >>>>> If you make a static it will work, but of course share its value
    >>>>> between all x objects.

    >>
    >>>>> As a workaround, you can add an overload that gets the correct
    >>>>> value:

    >>
    >>>>> void foo()
    >>>>> {
    >>>>> foo(a);
    >>>>> }

    >>
    >>>>> Bo Persson

    >>
    >>>> I think I could guess that it is not allowed by the standard,
    >>>> but my question was originally about why it is not allowed.
    >>>> Unless there is a good reason for disallowing it in the
    >>>> standard, the standard could have allowed non static default
    >>>> argument as well.

    >>
    >>> The standard usually doesn't give any reason for the rules, it
    >>> just states what they are.

    >>
    >>> In this case, I agree that it would be feasible for the caller to
    >>> supply not only the 'this' pointer, but also 'this->a' as a
    >>> parameter value (with the exception that as a is private, it is a
    >>> bit questionable if it should :).

    >>
    >>> I can only imagine that as the 'this' pointer is formally
    >>> provided by magic inside the member function, perhaps we cannot
    >>> require that the caller knows what it is, so in theory there are
    >>> cases where it cannot provide this->a.

    >>
    >>> Bo Persson

    >>
    >> Could you post some example /cases where it doesn't know what
    >> this->a is? In earlier post by Bart, he points to the fact that
    >> variable a is inaccessible in the scope of main because it is
    >> private. But here we are not talking about visibility at the
    >> language level but visibility at the compiler level. Compiler does
    >> have knowledge / visibility of this->a, while in the context of
    >> language / scope, surely the variable is not accessible. I would
    >> assume that default arguments are something that are dealt by the
    >> compiler and during the runtime.

    >
    > Please read that last line as
    >
    > I would assume that default arguments are something that are dealt
    > by the compiler and NOT during the runtime.


    No, I don't have any good examples. However, I could imagine that with
    multiple inheritance and virtual base classes, perhaps the caller
    cannot always determine the value of the 'this' pointer. The standard
    only requires it to be present INSIDE the called function.


    Bo Persson
     
    Bo Persson, Sep 23, 2009
    #18
  19. [snipped problem, why the compiler does not allow const member
    variables as default arguments, see OP's example:
    class x
    {
    private :
    const int a;
    public :
    X() : a(1)
    {}
    void foo(int arg = a)
    {
    cout << arg << endl;
    }
    };
    ]

    > Having looked at the various posts, I feel that this discussion is
    > still inconclusive and I would agree with Fred that it is simply not
    > allowed by the standard, probably to ease the job of compiler writer.


    I think that may be the main reason. Since the computation of the
    default argument could be an arbitrarily complex expression, it would
    be quite a pain to fully parse such code (although I see no technical
    reason why this should be impossible), so I guess that the C writers
    decided to allow only literals (there is still enough compiler work
    necessary to convert the literals to the actual paramter type: you can
    provided char* literals for std::string parameters).

    If you really wanted to provide more elaborated default argument
    computations you could easily split the method into two methods.

    > I think the other angle to look at this problem can be from a
    > perspective of multi-threading. I am not aware if language designers
    > keep multi threading issues while designing languages or not, but it
    > appears that default argument with non static member variable could be
    > an issue in multi-threading environments. For example on a multi
    > processor system if one thread is writing to the variable and the
    > other one is reading the same variable to be passed as default
    > argument, without being protected by a lock, it can lead to different
    > behaviors / data passed based on who reads / writes first.


    Right.

    > But if the
    > programmer is aware of this issue then from a language design
    > perspective I guess it is not an issue.


    True. Keeping things in synch (under C) is definitely the responsibily
    of the programmer, so this consideration is certainly not the reason.

    Regards,
    Stuart
     
    Stuart Redmann, Sep 24, 2009
    #19
  20. On Sep 24, 8:59 am, Stuart Redmann <> wrote:
    > [snipped problem, why the compiler does not allow const member
    > variables as default arguments, see OP's example:
    > class x
    > {
    > private :
    >   const int a;
    > public :
    >   X() : a(1)
    >   {}
    >   void foo(int arg = a)
    >   {
    >     cout << arg << endl;
    >   }};
    >
    > ]
    >
    > > Having looked at the various posts, I feel that this discussion is
    > > still inconclusive and I would agree with Fred that it is simply not
    > > allowed by the standard, probably to ease the job of compiler writer.

    >
    > I think that may be the main reason. Since the computation of the
    > default argument could be an arbitrarily complex expression, it would
    > be quite a pain to fully parse such code (although I see no technical
    > reason why this should be impossible), so I guess that the C writers
    > decided to allow only literals (there is still enough compiler work
    > necessary to convert the literals to the actual paramter type: you can
    > provided char* literals for std::string parameters).


    Actually, you ARE allowed to use an arbitrarily complex expression as
    a default argument.
    The problem is that the default argument expression is 'evaluated' in
    two different contexts. At the point where the expression occurs in
    the sourcce code, it is 'evaluated'to determine which objects and
    functions are referenced. At this point, all identifiers must be bound
    to an actual object or function.
    When the default argument is used in a function call, then it is
    evaluated for a second time, not to determine the actual value of the
    default argument.

    For example:

    int a = 0;
    int f(double x) {return x*100;}
    int g(int x=f(a)); /* binds default argument to f(double) and ::a */

    int f(int x) {return x;}

    void m()
    {
    int a = 1;
    ::a = 2;
    g(); /* calls g(f(2)) -> g(200) */
    }

    As you can see, this mechanism precludes using information that is
    only known at the call site (such as the object on which a member-
    function is being invoked).

    >
    > If you really wanted to provide more elaborated default argument
    > computations you could easily split the method into two methods.
    >
    > > I think the other angle to look at this problem can be from a
    > > perspective of multi-threading. I am not aware if language designers
    > > keep multi threading issues while designing languages or not


    I think you can safely assume that they only do so if the language has
    built-in (specified in the language definition) support for multi-
    threading.

    > Regards,
    > Stuart


    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Sep 24, 2009
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,237
    Smokey Grindel
    Dec 2, 2006
  2. Replies:
    11
    Views:
    1,151
  3. Javier
    Replies:
    2
    Views:
    623
    James Kanze
    Sep 4, 2007
  4. fungus
    Replies:
    13
    Views:
    949
    fungus
    Oct 31, 2008
  5. Dave Slayton
    Replies:
    1
    Views:
    206
    Ben Morrow
    Mar 11, 2007
Loading...

Share This Page