function pointer as template argument

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

    function pointer as template argument

    Hello,

    I want to build a library to help exporting c++ functions to a
    scripting languagge. The scripting language provides a function to
    register functions like:

    ANY f0()
    ANY f1(ANY)
    ANY f2(ANY, ANY)
    ANY f3(ANY, ANY, ANY)
    ...

    where ANY is an opaque type, with functions available to convert from
    and to basic C types.

    I would like to avoid writing a wrapper for any function I have to
    export.
    My first try (restricted to functions of one argument, but can easily
    be extended):

    //------------------------------------------------

    template <class T_return, class T_arg, T_return (*fn)(T_arg)>
    struct Translator1 {
    static ANY proc(ANY arg)
    {
    T_arg a = from_any<T_arg> (arg); // Conversion from ANY to arg type
    T_return r = to_any<T_return >((*fn)(a)); // Conversion from return
    type to ANY
    return r;
    }
    };

    int foo(int a) { return a*10; }

    typedef Translator1<int , int, foo> FN;
    c_reg_function( FN::proc );

    //-----------------------------------------------------

    Ok, that works ! But it would be fine to let the compiler guess the
    type of the arguments:

    //--------------------------------------------------------

    template <class T_return, class T_arg>
    void export_fn(T_ret urn (*fn)(T_arg))
    {
    c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg)) ;
    }

    export_fn(foo);

    //-----------------------------------------------------------------

    But now, something goes wrong (g++ v3.3) !!!

    test.cc: En function `void export_fn(T_ret urn (*)(T_arg)) [with
    T_return = int,
    T_arg = int]':
    test.cc:43: instantiated from here
    test.cc:33: error: `fn' is not a valid template argument
    test.cc:33: error: it must be the address of a function with external
    linkage
    test.cc:33: error: `arg' undeclared (first use this function)
    test.cc:33: error: (Each undeclared identifier is reported only once
    for each
    function it appears in.)
    test.cc:33: error: `<type error>' is not a class type


    I'm afraid that the compiler cannot expand a template class within a
    template function with fewer template arguments ! I cannot use
    functors because the register function expects C functions !

    Any good idea ? I cannot think of any solution that avoids the use of
    dirty preprocesor macros.

    Thanks !!!


    A reduced version of the code is provided so that you can try
    yourself:

    ////////////////////////////////////////////
    #include <iostream>

    using namespace std;

    typedef long ANY;

    void c_reg_function( ANY (*fn)(ANY)); // external c library function

    void c_reg_function( ANY (*fn)(ANY))
    {
    cout << "Registro: " << (*fn)(2) << endl;
    }

    template<class T> ANY to_any(T); // ANY conversion functions
    template<class T> T from_any(ANY);

    template<> int from_any(ANY a) { return a; }
    template<> ANY to_any(int a) { return a; }

    template <class T_return, class T_arg, T_return (*fn)(T_arg)>
    struct Translator1 {
    static ANY proc(ANY arg)
    {
    T_arg a = from_any<T_arg> (arg);
    T_return r = to_any<T_return >((*fn)(a));
    return r;
    }
    };

    template <class T_return, class T_arg>
    void export_fn(T_ret urn (*fn)(T_arg))
    {
    c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg)) ;
    }

    int foo(int a) { return a*10; }

    int main(int argc, char** argv)
    {
    typedef Translator1<int , int, foo> FN;
    c_reg_function( FN::proc );

    export_fn(foo);

    }
    /////////////////////////////////////7
  • David Hilsee

    #2
    Re: function pointer as template argument

    "vpadial" <victormorilla@ yahoo.es> wrote in message
    news:e9fa2bb.04 10061358.415890 75@posting.goog le.com...[color=blue]
    > Hello,
    >
    > I want to build a library to help exporting c++ functions to a
    > scripting languagge. The scripting language provides a function to
    > register functions like:
    >
    > ANY f0()
    > ANY f1(ANY)
    > ANY f2(ANY, ANY)
    > ANY f3(ANY, ANY, ANY)
    > ...
    >
    > where ANY is an opaque type, with functions available to convert from
    > and to basic C types.
    >
    > I would like to avoid writing a wrapper for any function I have to
    > export.
    > My first try (restricted to functions of one argument, but can easily
    > be extended):
    >
    > //------------------------------------------------
    >
    > template <class T_return, class T_arg, T_return (*fn)(T_arg)>
    > struct Translator1 {
    > static ANY proc(ANY arg)
    > {
    > T_arg a = from_any<T_arg> (arg); // Conversion from ANY to arg type
    > T_return r = to_any<T_return >((*fn)(a)); // Conversion from return
    > type to ANY
    > return r;
    > }
    > };
    >
    > int foo(int a) { return a*10; }
    >
    > typedef Translator1<int , int, foo> FN;
    > c_reg_function( FN::proc );
    >
    > //-----------------------------------------------------
    >
    > Ok, that works ! But it would be fine to let the compiler guess the
    > type of the arguments:
    >
    > //--------------------------------------------------------
    >
    > template <class T_return, class T_arg>
    > void export_fn(T_ret urn (*fn)(T_arg))
    > {
    > c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg)) ;
    > }
    >
    > export_fn(foo);
    >
    > //-----------------------------------------------------------------
    >
    > But now, something goes wrong (g++ v3.3) !!!
    >
    > test.cc: En function `void export_fn(T_ret urn (*)(T_arg)) [with
    > T_return = int,
    > T_arg = int]':
    > test.cc:43: instantiated from here
    > test.cc:33: error: `fn' is not a valid template argument
    > test.cc:33: error: it must be the address of a function with external
    > linkage
    > test.cc:33: error: `arg' undeclared (first use this function)
    > test.cc:33: error: (Each undeclared identifier is reported only once
    > for each
    > function it appears in.)
    > test.cc:33: error: `<type error>' is not a class type
    >
    >
    > I'm afraid that the compiler cannot expand a template class within a
    > template function with fewer template arguments ! I cannot use
    > functors because the register function expects C functions ![/color]

    It's not complaining about the number of arguments. The value of "fn" won't
    be known until runtime. You can't expect the compiler to instantiate a
    template based on its value if it can't possibly know the value.

    Why is it a template argument in the first place? Couldn't you just write
    it like this:

    template <class T_return, class T_arg>
    struct Translator1 {
    static ANY proc(ANY arg, T_return (*fn)(T_arg))
    {
    T_arg a = from_any<T_arg> (arg);
    T_return r = to_any<T_return >((*fn)(a));
    return r;
    }
    };

    template <class T_return, class T_arg>
    void export_fn(T_ret urn (*fn)(T_arg))
    {
    c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg,f n));
    }

    or do you plan on doing some specializations based on its value?

    --
    David Hilsee


    Comment

    • David Hilsee

      #3
      Re: function pointer as template argument

      "David Hilsee" <davidhilseenew s@yahoo.com> wrote in message
      news:rvmdnR9hcN hV7_ncRVn-uA@comcast.com. ..
      [...][color=blue]
      > c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg,f n));[/color]

      Sorry, I meant

      c_reg_function( Translator1<T_r eturn, T_arg>::proc(ar g,fn));

      --
      David Hilsee



      Comment

      • David Hilsee

        #4
        Re: function pointer as template argument

        "David Hilsee" <davidhilseenew s@yahoo.com> wrote in message
        news:rvmdnR9hcN hV7_ncRVn-uA@comcast.com. ..[color=blue]
        > "vpadial" <victormorilla@ yahoo.es> wrote in message
        > news:e9fa2bb.04 10061358.415890 75@posting.goog le.com...[color=green]
        > > Hello,
        > >
        > > I want to build a library to help exporting c++ functions to a
        > > scripting languagge. The scripting language provides a function to
        > > register functions like:
        > >
        > > ANY f0()
        > > ANY f1(ANY)
        > > ANY f2(ANY, ANY)
        > > ANY f3(ANY, ANY, ANY)
        > > ...
        > >
        > > where ANY is an opaque type, with functions available to convert from
        > > and to basic C types.
        > >
        > > I would like to avoid writing a wrapper for any function I have to
        > > export.
        > > My first try (restricted to functions of one argument, but can easily
        > > be extended):
        > >
        > > //------------------------------------------------
        > >
        > > template <class T_return, class T_arg, T_return (*fn)(T_arg)>
        > > struct Translator1 {
        > > static ANY proc(ANY arg)
        > > {
        > > T_arg a = from_any<T_arg> (arg); // Conversion from ANY to arg type
        > > T_return r = to_any<T_return >((*fn)(a)); // Conversion from return
        > > type to ANY
        > > return r;
        > > }
        > > };
        > >
        > > int foo(int a) { return a*10; }
        > >
        > > typedef Translator1<int , int, foo> FN;
        > > c_reg_function( FN::proc );
        > >
        > > //-----------------------------------------------------
        > >
        > > Ok, that works ! But it would be fine to let the compiler guess the
        > > type of the arguments:
        > >
        > > //--------------------------------------------------------
        > >
        > > template <class T_return, class T_arg>
        > > void export_fn(T_ret urn (*fn)(T_arg))
        > > {
        > > c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg)) ;
        > > }
        > >
        > > export_fn(foo);
        > >
        > > //-----------------------------------------------------------------
        > >
        > > But now, something goes wrong (g++ v3.3) !!!
        > >
        > > test.cc: En function `void export_fn(T_ret urn (*)(T_arg)) [with
        > > T_return = int,
        > > T_arg = int]':
        > > test.cc:43: instantiated from here
        > > test.cc:33: error: `fn' is not a valid template argument
        > > test.cc:33: error: it must be the address of a function with external
        > > linkage
        > > test.cc:33: error: `arg' undeclared (first use this function)
        > > test.cc:33: error: (Each undeclared identifier is reported only once
        > > for each
        > > function it appears in.)
        > > test.cc:33: error: `<type error>' is not a class type
        > >
        > >
        > > I'm afraid that the compiler cannot expand a template class within a
        > > template function with fewer template arguments ! I cannot use
        > > functors because the register function expects C functions ![/color]
        >
        > It's not complaining about the number of arguments. The value of "fn"[/color]
        won't[color=blue]
        > be known until runtime. You can't expect the compiler to instantiate a
        > template based on its value if it can't possibly know the value.
        >
        > Why is it a template argument in the first place? Couldn't you just write
        > it like this:
        >
        > template <class T_return, class T_arg>
        > struct Translator1 {
        > static ANY proc(ANY arg, T_return (*fn)(T_arg))
        > {
        > T_arg a = from_any<T_arg> (arg);
        > T_return r = to_any<T_return >((*fn)(a));
        > return r;
        > }
        > };
        >
        > template <class T_return, class T_arg>
        > void export_fn(T_ret urn (*fn)(T_arg))
        > {
        > c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg,f n));
        > }
        > [...][/color]

        After rereading your post several times, I realized that I did not fully
        understand what you were trying to do. I was confused by the sample code
        that appeared to be an attempt at invoking "proc" (Translator1<T_ return,
        T_arg, fn>::proc(arg)) . I think the line "c_reg_function ( FN::proc );"
        should have instead been "c_reg_function ( &FN::proc );" For some reason, I
        thought you had omitted some arguments to the function call on that line.
        Sorry for any confusion my responses may have caused.

        Even so, I can't think of any way that you could have the compiler easily
        and automatically determine the return type and arguments in the way that
        you need them to be determined. The function template you wrote won't work
        for the reason a mentioned before: the value is not known at compile time.

        --
        David Hilsee


        Comment

        • vpadial

          #5
          Re: function pointer as template argument

          "David Hilsee" <davidhilseenew s@yahoo.com> wrote in message news:<KcWdnQqoz 6zn7vncRVn-tQ@comcast.com> ...[color=blue]
          > "David Hilsee" <davidhilseenew s@yahoo.com> wrote in message
          > news:rvmdnR9hcN hV7_ncRVn-uA@comcast.com. ..
          > [...][color=green]
          > > c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg,f n));[/color]
          >
          > Sorry, I meant
          >
          > c_reg_function( Translator1<T_r eturn, T_arg>::proc(ar g,fn));[/color]

          The problem is that c_reg_function expects a pointer to a function (ANY (*fn)(ANY))

          Comment

          • Tom Widmer

            #6
            Re: function pointer as template argument

            On 6 Oct 2004 14:58:45 -0700, victormorilla@y ahoo.es (vpadial) wrote:
            [color=blue]
            >Hello,
            >
            >I want to build a library to help exporting c++ functions to a
            >scripting languagge. The scripting language provides a function to
            >register functions like:
            >
            > ANY f0()
            > ANY f1(ANY)
            > ANY f2(ANY, ANY)
            > ANY f3(ANY, ANY, ANY)
            > ...
            >
            >where ANY is an opaque type, with functions available to convert from
            >and to basic C types.
            >
            >I would like to avoid writing a wrapper for any function I have to
            >export.
            >My first try (restricted to functions of one argument, but can easily
            >be extended):
            >
            >//------------------------------------------------
            >
            >template <class T_return, class T_arg, T_return (*fn)(T_arg)>
            >struct Translator1 {
            > static ANY proc(ANY arg)
            > {
            > T_arg a = from_any<T_arg> (arg); // Conversion from ANY to arg type
            > T_return r = to_any<T_return >((*fn)(a)); // Conversion from return
            >type to ANY
            > return r;
            > }
            >};
            >
            >int foo(int a) { return a*10; }
            >
            >typedef Translator1<int , int, foo> FN;
            >c_reg_function ( FN::proc );
            >
            >//-----------------------------------------------------
            >
            >Ok, that works ! But it would be fine to let the compiler guess the
            >type of the arguments:
            >
            >//--------------------------------------------------------
            >
            >template <class T_return, class T_arg>
            >void export_fn(T_ret urn (*fn)(T_arg))
            >{
            > c_reg_function( Translator1<T_r eturn, T_arg, fn>::proc(arg)) ;
            >}
            >
            >export_fn(foo) ;
            >
            >//-----------------------------------------------------------------
            >
            >But now, something goes wrong (g++ v3.3) !!!
            >
            >test.cc: En function `void export_fn(T_ret urn (*)(T_arg)) [with
            >T_return = int,
            > T_arg = int]':
            >test.cc:43: instantiated from here
            >test.cc:33: error: `fn' is not a valid template argument
            >test.cc:33: error: it must be the address of a function with external
            >linkage
            >test.cc:33: error: `arg' undeclared (first use this function)
            >test.cc:33: error: (Each undeclared identifier is reported only once
            >for each
            > function it appears in.)
            >test.cc:33: error: `<type error>' is not a class type
            >
            >
            >I'm afraid that the compiler cannot expand a template class within a
            >template function with fewer template arguments ! I cannot use
            >functors because the register function expects C functions !
            >
            >Any good idea ? I cannot think of any solution that avoids the use of
            >dirty preprocesor macros.[/color]

            The problem is that your function argument "fn" has a runtime value,
            but template arguments are required to be known at compile time.

            I can't think of a standard C++ solution, but I can think of a gcc
            specific solution - typeof. e.g.

            template <typename FuncType, FuncType func>
            struct Translator1
            {
            //need to write FuncArgs, using partial specialization
            typedef FuncArgs<FuncTy pe>::first_argu ment_type T_arg;
            typedef FuncArgs<FuncTy pe>::return_typ e T_return;

            static ANY proc(ANY arg)
            {
            T_arg a = from_any<T_arg> (arg); // Conversion from ANY to arg type
            T_return r = to_any<T_return >((*fn)(a));
            return r;
            }
            };

            c_reg_function( &Translator1<ty peof(&foo), foo>::proc);

            Whether you can put up with the non-portability is up to you.

            Tom

            Comment

            • Tom Widmer

              #7
              Re: function pointer as template argument

              On 6 Oct 2004 14:58:45 -0700, victormorilla@y ahoo.es (vpadial) wrote:
              [color=blue]
              >Hello,
              >
              >I want to build a library to help exporting c++ functions to a
              >scripting languagge.[/color]

              Actually, what you're doing has been done several times before. This
              book would be helpful:
              Abrahams and Gurtovoy have written something close to a classic... marvelous fun to read... Read the complete book review by Jack J. Woehr, Dr.


              Here's an example of a library that binds C++ and Python:


              Comment

              • vpadial

                #8
                Re: function pointer as template argument

                Tom Widmer <tom_usenet@hot mail.com> wrote in message news:<k79am0to6 28sd8hid6qmg1gr jk14enf5ld@4ax. com>...[color=blue]
                >
                > The problem is that your function argument "fn" has a runtime value,
                > but template arguments are required to be known at compile time.
                >
                > I can't think of a standard C++ solution, but I can think of a gcc
                > specific solution - typeof. e.g.
                >
                > template <typename FuncType, FuncType func>
                > struct Translator1
                > {
                > //need to write FuncArgs, using partial specialization
                > typedef FuncArgs<FuncTy pe>::first_argu ment_type T_arg;
                > typedef FuncArgs<FuncTy pe>::return_typ e T_return;
                >
                > static ANY proc(ANY arg)
                > {
                > T_arg a = from_any<T_arg> (arg); // Conversion from ANY to arg type
                > T_return r = to_any<T_return >((*fn)(a));
                > return r;
                > }
                > };
                >
                > c_reg_function( &Translator1<ty peof(&foo), foo>::proc);
                >
                > Whether you can put up with the non-portability is up to you.
                >[/color]

                Thanks Tom, but I can't get it working. Could you explain better the
                use of FuncArgs ? How can I specialize types of a template class ?
                Must I specialize FuncArgs for any new function signature ?

                Thanks in advance

                Comment

                • vpadial

                  #9
                  Re: function pointer as template argument

                  victormorilla@y ahoo.es (vpadial) wrote in message news:<e9fa2bb.0 410080831.2d00b daf@posting.goo gle.com>...[color=blue]
                  > Tom Widmer <tom_usenet@hot mail.com> wrote in message news:<k79am0to6 28sd8hid6qmg1gr jk14enf5ld@4ax. com>...[color=green]
                  > >
                  > > The problem is that your function argument "fn" has a runtime value,
                  > > but template arguments are required to be known at compile time.
                  > >
                  > > I can't think of a standard C++ solution, but I can think of a gcc
                  > > specific solution - typeof. e.g.
                  > >
                  > > template <typename FuncType, FuncType func>
                  > > struct Translator1
                  > > {
                  > > //need to write FuncArgs, using partial specialization
                  > > typedef FuncArgs<FuncTy pe>::first_argu ment_type T_arg;
                  > > typedef FuncArgs<FuncTy pe>::return_typ e T_return;
                  > >
                  > > static ANY proc(ANY arg)
                  > > {
                  > > T_arg a = from_any<T_arg> (arg); // Conversion from ANY to arg type
                  > > T_return r = to_any<T_return >((*fn)(a));
                  > > return r;
                  > > }
                  > > };
                  > >
                  > > c_reg_function( &Translator1<ty peof(&foo), foo>::proc);
                  > >
                  > > Whether you can put up with the non-portability is up to you.
                  > >[/color]
                  >
                  > Thanks Tom, but I can't get it working. Could you explain better the
                  > use of FuncArgs ? How can I specialize types of a template class ?
                  > Must I specialize FuncArgs for any new function signature ?
                  >
                  > Thanks in advance[/color]

                  Don't bother. I've seen Boost provides function_traits that I guess is
                  equivalent to your FuncArgs class:


                  Thanks for your help

                  Comment

                  Working...