Omitting function default args when no prototype is available?

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

    Omitting function default args when no prototype is available?

    gcc 3.3 allowed a typedef for a function pointer to contain default
    argument specifications; for example:

    typedef int (*foo) (int, int, int=0, bar=0);

    However, it turns out that this is illegal and gcc 3.4 prohibits it.
    Problem: I've got a lot of code that uses this 'feature', and I can't
    move the default specifications into the function declaration or
    definition, because they're not visible. This means that I can no
    longer call foo-type functions without supplying all the arguments,
    which is causing me problems. In addition, I can't even find a
    workaround that compiles.

    The current situation is that I have a library which has:

    typedef int (*foo) (int, int, int=0, bar=0);
    class A {
    ...
    foo user_func;

    A(foo user_func_) :
    user_func(user_ func_) {...}
    };

    The library user supplies 'user_func_', and I call 'user_func' in the
    library code with a variable number of parameters, using the defaults.
    Within the library itself, there are no user_func declarations or
    definitions.

    The only potential fix I can see is to manually expand out all the
    typedefs, but this doesn't work. I would have to write:

    class A {
    ...
    int (*user_func) (int, int, int=0, bar=0);

    A(foo user_func_) :
    user_func(user_ func_) {...}
    };

    gcc doesn't allow this, because I'm declaring a pointer, and not a
    function, and so I can't supply defaults.

    Any ideas?

    Cheers -

    AL
  • John Carson

    #2
    Re: Omitting function default args when no prototype is available?

    "Andy Lomax" <abuse@[127.0.0.1]> wrote in message
    news:ao28c19onn 7tftfvhurg48fib m9ajl42nc@4ax.c om[color=blue]
    > gcc 3.3 allowed a typedef for a function pointer to contain default
    > argument specifications; for example:
    >
    > typedef int (*foo) (int, int, int=0, bar=0);
    >
    > However, it turns out that this is illegal and gcc 3.4 prohibits it.
    > Problem: I've got a lot of code that uses this 'feature', and I can't
    > move the default specifications into the function declaration or
    > definition, because they're not visible. This means that I can no
    > longer call foo-type functions without supplying all the arguments,
    > which is causing me problems. In addition, I can't even find a
    > workaround that compiles.
    >
    > The current situation is that I have a library which has:
    >
    > typedef int (*foo) (int, int, int=0, bar=0);
    > class A {
    > ...
    > foo user_func;
    >
    > A(foo user_func_) :
    > user_func(user_ func_) {...}
    > };
    >
    > The library user supplies 'user_func_', and I call 'user_func' in the
    > library code with a variable number of parameters, using the defaults.
    > Within the library itself, there are no user_func declarations or
    > definitions.
    >
    > The only potential fix I can see is to manually expand out all the
    > typedefs, but this doesn't work. I would have to write:
    >
    > class A {
    > ...
    > int (*user_func) (int, int, int=0, bar=0);
    >
    > A(foo user_func_) :
    > user_func(user_ func_) {...}
    > };
    >
    > gcc doesn't allow this, because I'm declaring a pointer, and not a
    > function, and so I can't supply defaults.
    >
    > Any ideas?[/color]

    Wrap the call using the function pointer in an inline function:

    int Wrapper (int a, int b, int c=0, bar d =0)
    {
    user_func(a,b,c ,d);
    }

    and call Wrapper rather than user_func (do whatever renaming of the Wrapper
    function and the pointer that you find convenient).

    --
    John Carson

    Comment

    • Andy Lomax

      #3
      Re: Omitting function default args when no prototype is available?

      On Fri, 1 Jul 2005 02:19:35 +1000, "John Carson"
      <jcarson_n_o_sp _am_@netspace.n et.au> wrote:

      [color=blue][color=green]
      >> Any ideas?[/color]
      >
      >Wrap the call using the function pointer in an inline function:
      >
      >int Wrapper (int a, int b, int c=0, bar d =0)
      >{
      > user_func(a,b,c ,d);
      >}
      >[/color]

      Thanks, that does seem to be the way to go.

      But this raises a more general issue - there seems to be no way to use
      a default parameter if you only have a pointer to a function. Test
      case below.

      Cheers -

      AL
      -------------------------------------------------
      #include <iostream>
      typedef void (*foo_t)(int,in t,int,int);

      void foo(int a, int b, int c=0, int d=0) {
      std::cout << a << b << c << d << std::endl;
      }

      void indirect_foo(fo o_t fooptr) {
      fooptr(1, 2, 3, 4); // Ok
      fooptr(1, 2); // Not Ok: doesn't compile
      }

      int main() {
      indirect_foo(fo o);
      }
      -------------------------------------------------

      Comment

      • Victor Bazarov

        #4
        Re: Omitting function default args when no prototype is available?

        Andy Lomax wrote:[color=blue]
        > [..] this raises a more general issue - there seems to be no way to use
        > a default parameter if you only have a pointer to a function. [..][/color]

        Correct. That is expressly prohibited by the Standard (8.3.6/3).

        V

        Comment

        • Andy Lomax

          #5
          Re: Omitting function default args when no prototype is available?

          On Thu, 30 Jun 2005 17:11:40 -0400, Victor Bazarov
          <v.Abazarov@com Acast.net> wrote:
          [color=blue]
          >Andy Lomax wrote:[color=green]
          >> [..] this raises a more general issue - there seems to be no way to use
          >> a default parameter if you only have a pointer to a function. [..][/color]
          >
          >Correct. That is expressly prohibited by the Standard (8.3.6/3).
          >
          >V[/color]

          Thanks Victor - this prompted me to actually download the std. The
          answer is in 8.3.5/6: "A typedef of function type may be used to
          declare a function", which implies that 8.3.6/3 does implicitly cover
          typedefs as well. Work-around example below; this works on gcc 3.4.

          Cheers -

          AL
          -------------------------------------------------------
          #include <iostream>
          typedef void foo_t (int,int=0,int= 0,int=0);

          foo_t foo; // declaration of foo: not required here

          void foo(int a, int b, int c, int d) {
          std::cout << a << b << c << d << std::endl;
          }

          void indirect_foo(fo o_t fooptr) {
          fooptr(1, 2, 3, 4); // Ok: outputs '1234'
          fooptr(1, 2); // **Ok: outputs '1200'!!**
          }

          int main() {
          indirect_foo(fo o);
          }
          -------------------------------------------------------

          Comment

          • John Carson

            #6
            Re: Omitting function default args when no prototype is available?

            "Andy Lomax" <abuse@[127.0.0.1]> wrote in message
            news:j51ac1p677 3jmtosv1af4looo 2k39uluk6@4ax.c om[color=blue]
            > On Thu, 30 Jun 2005 17:11:40 -0400, Victor Bazarov
            > <v.Abazarov@com Acast.net> wrote:
            >[color=green]
            >> Andy Lomax wrote:[color=darkred]
            >>> [..] this raises a more general issue - there seems to be no way
            >>> to use a default parameter if you only have a pointer to a
            >>> function. [..][/color]
            >>
            >> Correct. That is expressly prohibited by the Standard (8.3.6/3).
            >>
            >> V[/color]
            >
            > Thanks Victor - this prompted me to actually download the std. The
            > answer is in 8.3.5/6: "A typedef of function type may be used to
            > declare a function", which implies that 8.3.6/3 does implicitly cover
            > typedefs as well. Work-around example below; this works on gcc 3.4.
            >
            > Cheers -
            >
            > AL
            > -------------------------------------------------------
            > #include <iostream>
            > typedef void foo_t (int,int=0,int= 0,int=0);
            >
            > foo_t foo; // declaration of foo: not required here
            >
            > void foo(int a, int b, int c, int d) {
            > std::cout << a << b << c << d << std::endl;
            > }
            >
            > void indirect_foo(fo o_t fooptr) {
            > fooptr(1, 2, 3, 4); // Ok: outputs '1234'
            > fooptr(1, 2); // **Ok: outputs '1200'!!**
            > }
            >
            > int main() {
            > indirect_foo(fo o);
            > }[/color]


            This is a non-standard gcc extension. It doesn't work with Comeau or VC++.


            --
            John Carson

            Comment

            • Andy Lomax

              #7
              Re: Omitting function default args when no prototype is available?

              On Fri, 1 Jul 2005 19:49:03 +1000, "John Carson"
              <jcarson_n_o_sp _am_@netspace.n et.au> wrote:
              [color=blue]
              >"Andy Lomax" <abuse@[127.0.0.1]> wrote in message[color=green]
              >> typedef void foo_t (int,int=0,int= 0,int=0);[/color]
              >This is a non-standard gcc extension. It doesn't work with Comeau or VC++.[/color]

              Are you sure? 5.3.5/6 says:
              [color=blue]
              >A typedef of function type may be used to declare a function but shall not be used to define a function (8.4).
              >[Example:
              >typedef void F();
              >F fv; // ok: equivalent to void fv();
              >F fv { } // illformed
              >void fv() { } // ok: definition of fv
              >—end example][/color]

              8.3.6/3 says:
              [color=blue]
              >A default argument expression shall be specified only in the parameterdeclar ationclause
              >of a function
              >declaration or in a templateparamet er
              >(14.1).[/color]

              This indicates, more or less, to me that a typedef of function type is
              *equivalent* to a function declaration (see the comment in the
              example), and so qualifies under 8.3.6/3.

              Under 'C++ extensions', the gcc online help says:
              [color=blue]
              >The use of default arguments in function pointers, function typedefs
              >and and other places where they are not permitted by the standard is
              >deprecated and will be removed from a future version of G++.[/color]

              This indicates that someone thought that default args in function
              typedefs are illegal. However, what actually happened in the 3.3 ->
              3.4 transition was that typedefs of function *pointer* types were
              deprecated, but typedefs of function types weren't deprecated... maybe
              somebody had second thoughts about what was or wasn't illegal?

              The other issue, of course, is that if it was actually illegal,
              despite 5.3.5/6, it would make it impossible to do something which is
              clearly Very Useful.

              Cheers

              AL

              Comment

              • John Carson

                #8
                Re: Omitting function default args when no prototype is available?

                "Andy Lomax" <abuse@[127.0.0.1]> wrote in message
                news:8u8ac1djbm 623cnp1gpkpkuj4 0qgcg63ro@4ax.c om[color=blue]
                > On Fri, 1 Jul 2005 19:49:03 +1000, "John Carson"
                > <jcarson_n_o_sp _am_@netspace.n et.au> wrote:
                >[color=green]
                >> "Andy Lomax" <abuse@[127.0.0.1]> wrote in message[color=darkred]
                >>> typedef void foo_t (int,int=0,int= 0,int=0);[/color]
                >> This is a non-standard gcc extension. It doesn't work with Comeau or
                >> VC++.[/color]
                >
                > Are you sure? 5.3.5/6 says:[/color]

                You mean 8.3.5/6
                [color=blue]
                >[color=green]
                >> A typedef of function type may be used to declare a function but
                >> shall not be used to define a function (8.4). [Example:
                >> typedef void F();
                >> F fv; // ok: equivalent to void fv();
                >> F fv { } // illformed
                >> void fv() { } // ok: definition of fv
                >> -end example][/color]
                >
                > 8.3.6/3 says:
                >[color=green]
                >> A default argument expression shall be specified only in the
                >> parameterdeclar ationclause
                >> of a function
                >> declaration or in a templateparamet er
                >> (14.1).[/color]
                >
                > This indicates, more or less, to me that a typedef of function type is
                > *equivalent* to a function declaration (see the comment in the
                > example), and so qualifies under 8.3.6/3.[/color]

                No, read the next sentence from 8.3.6/3 and especially the footnote:

                "This means that default arguments cannot appear, for example, in
                declarations of pointers to functions, references to functions, or typedef
                declarations."

                Something that explicit trumps anything you might infer.
                [color=blue]
                > Under 'C++ extensions', the gcc online help says:
                >[color=green]
                >> The use of default arguments in function pointers, function typedefs
                >> and and other places where they are not permitted by the standard is
                >> deprecated and will be removed from a future version of G++.[/color]
                >
                > This indicates that someone thought that default args in function
                > typedefs are illegal. However, what actually happened in the 3.3 ->
                > 3.4 transition was that typedefs of function *pointer* types were
                > deprecated, but typedefs of function types weren't deprecated... maybe
                > somebody had second thoughts about what was or wasn't illegal?[/color]

                More likely that they haven't got around to changing it yet.
                [color=blue]
                > The other issue, of course, is that if it was actually illegal,
                > despite 5.3.5/6, it would make it impossible to do something which is
                > clearly Very Useful.[/color]

                There are thousands of things that are illegal but which, at least in the
                opinion of some people, are Very Useful. Designing a language is incredibly
                difficult. It isn't enough to have rules that work in simple cases. You need
                rules that work (e.g., are free of ambiguities of interpretation) in
                situations of arbitrary complexity.

                --
                John Carson

                Comment

                • Andy Lomax

                  #9
                  Re: Omitting function default args when no prototype is available?

                  On Fri, 1 Jul 2005 22:01:22 +1000, "John Carson"
                  <jcarson_n_o_sp _am_@netspace.n et.au> wrote:
                  [color=blue]
                  >No, read the next sentence from 8.3.6/3 and especially the footnote:
                  >
                  >"This means that default arguments cannot appear, for example, in
                  >declarations of pointers to functions, references to functions, or typedef
                  >declarations ."[/color]

                  Ah, bu**er. Missed that.

                  Isn't it time you were out of the office? :)

                  Cheers -

                  AL

                  Comment

                  • Ben Pope

                    #10
                    Re: Omitting function default args when no prototype is available?

                    Andy Lomax wrote:[color=blue]
                    > On Fri, 1 Jul 2005 02:19:35 +1000, "John Carson"
                    > <jcarson_n_o_sp _am_@netspace.n et.au> wrote:
                    >
                    >
                    >[color=green][color=darkred]
                    >>>Any ideas?[/color]
                    >>
                    >>Wrap the call using the function pointer in an inline function:
                    >>
                    >>int Wrapper (int a, int b, int c=0, bar d =0)
                    >>{
                    >> user_func(a,b,c ,d);
                    >>}
                    >>[/color]
                    >
                    >
                    > Thanks, that does seem to be the way to go.
                    >
                    > But this raises a more general issue - there seems to be no way to use
                    > a default parameter if you only have a pointer to a function. Test
                    > case below.[/color]

                    Isn't this what Alexandrescu's "Generalise d Functors" do? OK, so it's not a typedef, but it does have value semantics, so you can use it as a prototype.

                    Ben
                    --
                    A7N8X FAQ: www.ben.pope.name/a7n8x_faq.html
                    Questions by email will likely be ignored, please use the newsgroups.
                    I'm not just a number. To many, I'm known as a String...

                    Comment

                    Working...