function default arguments from other arguments

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • tutmann

    #1

    function default arguments from other arguments

    Hello,

    to make it short, why does this not compile?

    class B {
    public:
    int b(void) { return 1;}
    }
    void f( B x, int i = x.b()) { }

    in gcc 3.3 I get error: 'x' was not declared in this scope

    But...I just declared x before. Why can't I use it?

    Henning

  • Alf P. Steinbach

    #2
    Re: function default arguments from other arguments

    * tutmann:
    Hello,
    >
    to make it short, why does this not compile?
    >
    class B {
    public:
    int b(void) { return 1;}
    }
    void f( B x, int i = x.b()) { }
    >
    in gcc 3.3 I get error: 'x' was not declared in this scope
    >
    But...I just declared x before. Why can't I use it?
    You mean, why does the language forbid that?

    Presumably to simplify things for the compilerm, but ask in [comp.std.c++].

    Simple workaround is to overload f.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?

    Comment

    • Bart

      #3
      Re: function default arguments from other arguments

      tutmann wrote:
      Hello,
      >
      to make it short, why does this not compile?
      >
      class B {
      public:
      int b(void) { return 1;}
      }
      void f( B x, int i = x.b()) { }
      >
      in gcc 3.3 I get error: 'x' was not declared in this scope
      >
      But...I just declared x before. Why can't I use it?
      GGG's message is extremely misleading actually. x is already declared
      at that point (and hides any other 'x' that may have been declared
      before), but cannot be used in a default argument expression. The
      reason is that the order of evaluation of function arguments is
      unspecified.

      An obvious workaround is a one-argument overload that calls the
      two-argument function.

      Regards,
      Bart.

      Comment

      • Salt_Peter

        #4
        Re: function default arguments from other arguments


        tutmann wrote:
        Hello,
        >
        to make it short, why does this not compile?
        >
        class B {
        public:
        int b(void) { return 1;}
        }
        semicolon required - B is a class declaration (and definition here)
        Also, int b() is attempting to return a literal - a const integer so...

        class B
        {
        public:
        int b() const { return 1; }
        }; // <- semicolon
        void f( B x, int i = x.b()) { }
        the first x is an instance of B, the second x does not exist, your
        compiler might accept the function if you reverse the parameters but
        its still a bad idea and officially undefined behaviour. Isn't the goal
        to pass an instance of B into the function enough? Why would you need
        to add an uneccessary integer parameter?

        #include <iostream>

        class B
        {
        public:
        int b() const { return 1; }
        };

        void f(B x)
        {
        int i = x.b(); // i needs not be in the parameter list
        std::cout << "i = " << i << std::endl;
        }

        int main()
        {
        B b;
        f(b);

        return 0;
        }

        /* output:
        i = 1
        */
        >
        in gcc 3.3 I get error: 'x' was not declared in this scope
        >
        But...I just declared x before. Why can't I use it?
        because gcc happens to process the parameters from right to left. So
        that x is undeclared. Note that the sequence with which the parameters
        gets processed doesn't matter. A Parameter should never, ever be a
        dependant of another parameter.

        You could have written something like:
        void f( B x, int i = B z.b()) { }
        but even that defies any logic here.

        Maybe if you wrote class B differently you might understand when more
        than one parameter makes sense.

        #include <iostream>

        class B
        {
        int b; // private member
        public:
        B(int n) : b(n) { } // ctor
        int get() const { return b; } // accessor
        };

        void bar( B xval, B yval = B(22) ) // 2 seperate values or instances
        { // one default
        param provided via ctor + copy
        std::cout << "\nx = " << xval.get() << std::endl;
        std::cout << "y = " << yval.get() << std::endl;
        int i = yval.get();
        std::cout << "i = " << i << std::endl;
        }

        int main()
        {
        B x(4);
        B y(9);
        bar(x, y); // pass by value
        bar(x); // yval is default initialized

        return 0;
        }

        /*
        x = 4
        y = 9
        i = 9

        x = 4
        y = 22
        i = 22
        */

        Consider getting a book like this one http://www.acceleratedcpp.com
        There is enough material there to last you a lifetime.

        Comment

        • Bart

          #5
          Re: function default arguments from other arguments

          Salt_Peter wrote:
          tutmann wrote:
          void f( B x, int i = x.b()) { }
          >
          the first x is an instance of B, the second x does not exist, your
          compiler might accept the function if you reverse the parameters but
          its still a bad idea and officially undefined behaviour.
          That is incorrect. According to official C++ rules, parameters declared
          before the default argument expression are in scope. The **order of
          evaluation** is unspecified, but it has nothing to do with scoping
          rules.
          in gcc 3.3 I get error: 'x' was not declared in this scope

          But...I just declared x before. Why can't I use it?
          >
          because gcc happens to process the parameters from right to left.
          That is not the reason for the error. GCC is right to give an error,
          but the error message is a lie.

          Regards,
          Bart.

          Comment

          Working...