function pointes and templates

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

    function pointes and templates

    Can anyone explain why this code fails to compile?

    #include <iostream>

    void func()
    {
    std::cout << "success!\n ";
    }

    struct S
    {
    template <class F>
    void method(const F& f)
    {
    f();
    }
    };

    int main()
    {
    S s;
    s.method(func);
    }

    but with a very slight change to main

    int main()
    {
    S s;
    s.method(&func) ; // change here
    }

    it compiles and works.

    john


  • tom_usenet

    #2
    Re: function pointes and templates

    On Tue, 6 Apr 2004 18:19:19 +0100, "John Harrison"
    <john_andronicu s@hotmail.com> wrote:
    [color=blue]
    >Can anyone explain why this code fails to compile?[/color]

    [snip]

    Looks like a compiler bug. It works fine on mine.

    Tom
    --
    C++ FAQ: http://www.parashift.com/c++-faq-lite/
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

    Comment

    • tom_usenet

      #3
      Re: function pointes and templates

      On Tue, 6 Apr 2004 18:19:19 +0100, "John Harrison"
      <john_andronicu s@hotmail.com> wrote:
      [color=blue]
      >Can anyone explain why this code fails to compile?[/color]

      [snip]

      Looks like a compiler bug. It works fine on mine.

      Tom
      --
      C++ FAQ: http://www.parashift.com/c++-faq-lite/
      C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

      Comment

      • Buster

        #4
        Re: function pointes and templates



        John Harrison wrote:
        [color=blue]
        > Can anyone explain why this code fails to compile?
        >
        > #include <iostream>
        >
        > void func()
        > {
        > std::cout << "success!\n ";
        > }
        >
        > struct S
        > {
        > template <class F>
        > void method(const F& f)
        > {
        > f();
        > }
        > };
        >
        > int main()
        > {
        > S s;
        > s.method(func);
        > }
        >
        > but with a very slight change to main
        >
        > int main()
        > {
        > S s;
        > s.method(&func) ; // change here
        > }
        >
        > it compiles and works.
        >
        > john[/color]

        I think it's because a function (not being an object) cannot be const,
        as illustrated by this, which does compile on my system:

        void f () { }

        int main ()
        {
        typedef void (& func_t) ();

        const func_t f = func;
        func_t g = f; // If g's referent were really const this wouldn't work.
        }

        Therefore, you can't initialize a reference-to-const-T with a function,
        since a function can be T but not const T.

        The same is not true of a pointer-to-function.

        --
        Regards,
        Buster.

        Comment

        • Buster

          #5
          Re: function pointes and templates



          John Harrison wrote:
          [color=blue]
          > Can anyone explain why this code fails to compile?
          >
          > #include <iostream>
          >
          > void func()
          > {
          > std::cout << "success!\n ";
          > }
          >
          > struct S
          > {
          > template <class F>
          > void method(const F& f)
          > {
          > f();
          > }
          > };
          >
          > int main()
          > {
          > S s;
          > s.method(func);
          > }
          >
          > but with a very slight change to main
          >
          > int main()
          > {
          > S s;
          > s.method(&func) ; // change here
          > }
          >
          > it compiles and works.
          >
          > john[/color]

          I think it's because a function (not being an object) cannot be const,
          as illustrated by this, which does compile on my system:

          void f () { }

          int main ()
          {
          typedef void (& func_t) ();

          const func_t f = func;
          func_t g = f; // If g's referent were really const this wouldn't work.
          }

          Therefore, you can't initialize a reference-to-const-T with a function,
          since a function can be T but not const T.

          The same is not true of a pointer-to-function.

          --
          Regards,
          Buster.

          Comment

          • Rob Williscroft

            #6
            Re: function pointes and templates

            John Harrison wrote in news:c4uoqp$2mp b1c$1@ID-196037.news.uni-berlin.de:
            [color=blue]
            > Can anyone explain why this code fails to compile?
            >
            > #include <iostream>
            >
            > void func()
            > {
            > std::cout << "success!\n ";
            > }
            >
            > struct S
            > {
            > template <class F>
            > void method(const F& f)
            > {
            > f();
            > }
            > };
            >
            > int main()
            > {
            > S s;
            > s.method(func);[/color]

            Both of these are ok:

            s.method( static_cast< void (*)() >( func ) );
            s.method( static_cast< void (&)() >( func ) );

            Both conversion's are standard conversions and have equal rank (*).
            Both require a futher qualification adjustment (add const).

            *) Exact Match.

            [color=blue]
            > }
            >
            > but with a very slight change to main
            >
            > int main()
            > {
            > S s;
            > s.method(&func) ; // change here
            > }
            >
            > it compiles and works.
            >[/color]

            There is no ambiguity, &func is a function pointer, only a
            futher qaulification adjustment is required. There is no
            ambiguos conversion to reference-to-function available.

            This is why functors are generaly passed by value.

            Rob.
            --

            Comment

            • Rob Williscroft

              #7
              Re: function pointes and templates

              John Harrison wrote in news:c4uoqp$2mp b1c$1@ID-196037.news.uni-berlin.de:
              [color=blue]
              > Can anyone explain why this code fails to compile?
              >
              > #include <iostream>
              >
              > void func()
              > {
              > std::cout << "success!\n ";
              > }
              >
              > struct S
              > {
              > template <class F>
              > void method(const F& f)
              > {
              > f();
              > }
              > };
              >
              > int main()
              > {
              > S s;
              > s.method(func);[/color]

              Both of these are ok:

              s.method( static_cast< void (*)() >( func ) );
              s.method( static_cast< void (&)() >( func ) );

              Both conversion's are standard conversions and have equal rank (*).
              Both require a futher qualification adjustment (add const).

              *) Exact Match.

              [color=blue]
              > }
              >
              > but with a very slight change to main
              >
              > int main()
              > {
              > S s;
              > s.method(&func) ; // change here
              > }
              >
              > it compiles and works.
              >[/color]

              There is no ambiguity, &func is a function pointer, only a
              futher qaulification adjustment is required. There is no
              ambiguos conversion to reference-to-function available.

              This is why functors are generaly passed by value.

              Rob.
              --

              Comment

              • John Harrison

                #8
                Re: function pointes and templates

                >[color=blue]
                > This is why functors are generaly passed by value.
                >[/color]

                Thanks, I'll remember the advice.

                john


                Comment

                • John Harrison

                  #9
                  Re: function pointes and templates

                  >[color=blue]
                  > This is why functors are generaly passed by value.
                  >[/color]

                  Thanks, I'll remember the advice.

                  john


                  Comment

                  • tom_usenet

                    #10
                    Re: function pointes and templates

                    On 06 Apr 2004 18:56:13 GMT, Rob Williscroft
                    <rtw@freenet.RE MOVE.co.uk> wrote:
                    [color=blue]
                    >Both of these are ok:
                    >
                    > s.method( static_cast< void (*)() >( func ) );
                    > s.method( static_cast< void (&)() >( func ) );
                    >
                    >Both conversion's are standard conversions and have equal rank (*).
                    >Both require a futher qualification adjustment (add const).
                    >
                    >*) Exact Match.[/color]

                    Yes, but 14.8.2.1/2 says that during template argument deduction, if
                    the argument is a function type, it is replaced with the function
                    pointer type, so there is no possibility of your second version above
                    being deduced. This is a template argument deduction issue, not
                    overloading - there is only one function called func and one called
                    method.
                    [color=blue]
                    >[color=green]
                    >> }
                    >>
                    >> but with a very slight change to main
                    >>
                    >> int main()
                    >> {
                    >> S s;
                    >> s.method(&func) ; // change here
                    >> }
                    >>
                    >> it compiles and works.
                    >>[/color]
                    >
                    >There is no ambiguity, &func is a function pointer, only a
                    >futher qaulification adjustment is required. There is no
                    >ambiguos conversion to reference-to-function available.
                    >
                    >This is why functors are generaly passed by value.[/color]

                    There is no ambiguity anyway - Comeau and GCC compile the original
                    code fine, without the &.

                    Tom
                    --
                    C++ FAQ: http://www.parashift.com/c++-faq-lite/
                    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

                    Comment

                    • tom_usenet

                      #11
                      Re: function pointes and templates

                      On 06 Apr 2004 18:56:13 GMT, Rob Williscroft
                      <rtw@freenet.RE MOVE.co.uk> wrote:
                      [color=blue]
                      >Both of these are ok:
                      >
                      > s.method( static_cast< void (*)() >( func ) );
                      > s.method( static_cast< void (&)() >( func ) );
                      >
                      >Both conversion's are standard conversions and have equal rank (*).
                      >Both require a futher qualification adjustment (add const).
                      >
                      >*) Exact Match.[/color]

                      Yes, but 14.8.2.1/2 says that during template argument deduction, if
                      the argument is a function type, it is replaced with the function
                      pointer type, so there is no possibility of your second version above
                      being deduced. This is a template argument deduction issue, not
                      overloading - there is only one function called func and one called
                      method.
                      [color=blue]
                      >[color=green]
                      >> }
                      >>
                      >> but with a very slight change to main
                      >>
                      >> int main()
                      >> {
                      >> S s;
                      >> s.method(&func) ; // change here
                      >> }
                      >>
                      >> it compiles and works.
                      >>[/color]
                      >
                      >There is no ambiguity, &func is a function pointer, only a
                      >futher qaulification adjustment is required. There is no
                      >ambiguos conversion to reference-to-function available.
                      >
                      >This is why functors are generaly passed by value.[/color]

                      There is no ambiguity anyway - Comeau and GCC compile the original
                      code fine, without the &.

                      Tom
                      --
                      C++ FAQ: http://www.parashift.com/c++-faq-lite/
                      C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

                      Comment

                      • Rob Williscroft

                        #12
                        Re: function pointes and templates

                        tom_usenet wrote in news:n8l770dngj 3qk49mnrkaq50b9 94cni0en8@4ax.c om:
                        [color=blue][color=green]
                        >>Both of these are ok:
                        >>
                        >> s.method( static_cast< void (*)() >( func ) );
                        >> s.method( static_cast< void (&)() >( func ) );
                        >>
                        >>Both conversion's are standard conversions and have equal rank (*).
                        >>Both require a futher qualification adjustment (add const).
                        >>
                        >>*) Exact Match.[/color]
                        >
                        > Yes, but 14.8.2.1/2 says that during template argument deduction, if
                        > the argument is a function type, it is replaced with the function
                        > pointer type, so there is no possibility of your second version above
                        > being deduced. This is a template argument deduction issue, not
                        > overloading - there is only one function called func and one called
                        > method.
                        >
                        >[/color]

                        1 Template argument deduction is done by comparing each function
                        template parameter type (call it P) with the type of the
                        corresponding argument of the call (call it A) as described below.

                        2 If P is not a reference type:

                        ...

                        — If A is a function type, the pointer type produced by the
                        function-to-pointer standard conversion (4.3) is used in
                        place of A for type deduction; otherwise,

                        ...

                        I quoted (1) as it describes P.

                        Given:

                        struct S
                        {
                        template <class F>
                        void method(const F& f)
                        {
                        f();
                        }
                        };

                        You seem to think "template parameter type (call it P)" is F where as
                        I think it is F const &.

                        Rob.
                        --

                        Comment

                        • Rob Williscroft

                          #13
                          Re: function pointes and templates

                          tom_usenet wrote in news:n8l770dngj 3qk49mnrkaq50b9 94cni0en8@4ax.c om:
                          [color=blue][color=green]
                          >>Both of these are ok:
                          >>
                          >> s.method( static_cast< void (*)() >( func ) );
                          >> s.method( static_cast< void (&)() >( func ) );
                          >>
                          >>Both conversion's are standard conversions and have equal rank (*).
                          >>Both require a futher qualification adjustment (add const).
                          >>
                          >>*) Exact Match.[/color]
                          >
                          > Yes, but 14.8.2.1/2 says that during template argument deduction, if
                          > the argument is a function type, it is replaced with the function
                          > pointer type, so there is no possibility of your second version above
                          > being deduced. This is a template argument deduction issue, not
                          > overloading - there is only one function called func and one called
                          > method.
                          >
                          >[/color]

                          1 Template argument deduction is done by comparing each function
                          template parameter type (call it P) with the type of the
                          corresponding argument of the call (call it A) as described below.

                          2 If P is not a reference type:

                          ...

                          — If A is a function type, the pointer type produced by the
                          function-to-pointer standard conversion (4.3) is used in
                          place of A for type deduction; otherwise,

                          ...

                          I quoted (1) as it describes P.

                          Given:

                          struct S
                          {
                          template <class F>
                          void method(const F& f)
                          {
                          f();
                          }
                          };

                          You seem to think "template parameter type (call it P)" is F where as
                          I think it is F const &.

                          Rob.
                          --

                          Comment

                          • tom_usenet

                            #14
                            Re: function pointes and templates

                            On 07 Apr 2004 14:06:18 GMT, Rob Williscroft
                            <rtw@freenet.RE MOVE.co.uk> wrote:
                            [color=blue]
                            >tom_usenet wrote in news:n8l770dngj 3qk49mnrkaq50b9 94cni0en8@4ax.c om:
                            >[color=green][color=darkred]
                            >>>Both of these are ok:
                            >>>
                            >>> s.method( static_cast< void (*)() >( func ) );
                            >>> s.method( static_cast< void (&)() >( func ) );
                            >>>
                            >>>Both conversion's are standard conversions and have equal rank (*).
                            >>>Both require a futher qualification adjustment (add const).
                            >>>
                            >>>*) Exact Match.[/color]
                            >>
                            >> Yes, but 14.8.2.1/2 says that during template argument deduction, if
                            >> the argument is a function type, it is replaced with the function
                            >> pointer type, so there is no possibility of your second version above
                            >> being deduced. This is a template argument deduction issue, not
                            >> overloading - there is only one function called func and one called
                            >> method.
                            >>
                            >>[/color]
                            >
                            >1 Template argument deduction is done by comparing each function
                            > template parameter type (call it P) with the type of the
                            > corresponding argument of the call (call it A) as described below.
                            >
                            >2 If P is not a reference type:[/color]

                            Oops, I missed the "If P is not a reference type". In this case, P is
                            a reference type of course, so the paragraph below doesn't apply.
                            [color=blue]
                            >
                            > ...
                            >
                            > — If A is a function type, the pointer type produced by the
                            > function-to-pointer standard conversion (4.3) is used in
                            > place of A for type deduction; otherwise,
                            >
                            > ...
                            >
                            >I quoted (1) as it describes P.
                            >
                            >Given:
                            >
                            >struct S
                            >{
                            > template <class F>
                            > void method(const F& f)
                            > {
                            > f();
                            > }
                            >};
                            >
                            >You seem to think "template parameter type (call it P)" is F where as
                            >I think it is F const &.[/color]

                            I just missed the "If P is not a reference type". So in fact, the
                            reverse is true; rather than choosing the function pointer type for
                            the template parameter, template argument deduction deduces F=void():

                            S::method<void( )>

                            Still, as I said before, there is nothing ambiguous about it and
                            overload resolution doesn't come into it, since 1 function is chosen
                            by TAD (S::method<void ()>) and there is only 1 valid conversion
                            sequence for the parameter to reach that type (void() ->
                            void(const&)() (direct reference binding).

                            The original example compiles fine with Comeau C++:

                            #include <iostream>
                            void func()
                            { std::cout << "success!\n "; }
                            struct S
                            {
                            template <class F>
                            void method(const F& f)
                            { f(); }
                            };
                            int main()
                            {
                            S s;
                            s.method(func);
                            }

                            Tom
                            --
                            C++ FAQ: http://www.parashift.com/c++-faq-lite/
                            C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

                            Comment

                            • Rob Williscroft

                              #15
                              Re: function pointes and templates

                              tom_usenet wrote in news:apin70dqi2 9l41754nlc16i6t 1d4a2u352@4ax.c om in
                              comp.lang.c++:
                              [color=blue][color=green]
                              >>You seem to think "template parameter type (call it P)" is F where as
                              >>I think it is F const &.[/color]
                              >
                              > I just missed the "If P is not a reference type". So in fact, the
                              > reverse is true; rather than choosing the function pointer type for
                              > the template parameter, template argument deduction deduces F=void():
                              >
                              > S::method<void( )>[/color]

                              Yep, I mistakenly assumed a conversion was nessacery for TAD, clearly
                              it isn't.
                              [color=blue]
                              >
                              > Still, as I said before, there is nothing ambiguous about it and
                              > overload resolution doesn't come into it, since 1 function is chosen
                              > by TAD (S::method<void ()>) and there is only 1 valid conversion
                              > sequence for the parameter to reach that type (void() ->
                              > void(const&)() (direct reference binding).
                              >[/color]

                              Thanks for the update.

                              Rob.
                              --

                              Comment

                              Working...