views:

301

answers:

6

UPDATE: After some additional reading, what I really wanted was guaranteed early binding (which should translated to an immediate call for non-virtual functions and non-PIC code), which can be done by passing a (member) function as a template parameter. The problem I had was that gcc < 4.5 and icc 11.1 can generate some funky instructions for member function pointer template parameter calls. AFAICT, gcc >= 4,5 and vs2008 handle these template parameter calls fine.

First of all, maybe literals is not the right term for this concept, but its the closest I could think of (not literals in the sense of functions as first class citizens).

The idea is that when you make a conventional function call, it compiles to something like this:

callq <immediate address>

But if you make a function call using a function pointer, it compiles to something like this:

mov    <memory location>,%rax
callq  *%rax

Which is all well and good. However, what if I'm writing a template library that requires a callback of some sort with a specified argument list and the user of the library is expected to know what function they want to call at compile time? Then I would like to write my template to accept a function literal as a template parameter. So, similar to

template <int int_literal> 
struct my_template {...};` 

I'd like to write

template <func_literal_t func_literal>
struct my_template {...};

and have calls to func_literal within my_template compile to callq <immediate address>.

Is there a facility in C++ for this, or a work around to achieve the same effect? If not, why not (e.g. some cataclysmic side effects)? How about C++0x or another language?

+1  A: 

CodeProject.com:

I've used on several platforms: http://www.codeproject.com/kb/cpp/FastDelegate.aspx

Saw in search results, will read: http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx

...or is this not the sort of thing you're looking for?

dash-tom-bang
First link still uses pointer call, thought they are faster than member function calls. Wasn't aware of the second, will look into it...
academicRobot
Didn't see before that you intended to read that second link. I played with it a minute ago and no dice. Actually, its a bit strange. There is an inner struct that embeds the call fine (in immediate mode), but that itself is called via function pointer. Think this is required to get interop between delegates, which is not a requirement here.
academicRobot
A: 

In the C++ language, the translators do not fold function names into the executable, they are lost and gone forever.

You can make a table of function name versus function address. Since C and C++ are stickler's for type information, this may be easier declared in assembly language. In the high level language, you would have to have a table for each different kind of function pointer. However, in assembly, it doesn't care. Although you could use a function with a switch in it to return a function pointer or execute the function.

An alternative is function IDs (enums) versus function addresses.

Thomas Matthews
I don't want to use the function name at run time, I want to use a surrogate for the function name at *compile time*. You're proposed solutions are still using function pointers at run time. Unless I misunderstand, please elaborate if this is the case.
academicRobot
A: 

At least if I understand your question correctly, this is trivial:

template <class func>
struct whatever { 
    operator()() { 
        func();
    }
};

The call to func(); will normally end up as a direct call to func() as you've asked, or if func() is small, its code will often be generated inline. If you want to improve the chances of its being generated inline, you generally want to write it as a functor (class that overloads operator()) instead of a normal function. As a normal function, you'll more often end up calling the actual function (but it'll be a direct call, not a call via a pointer).

Edit: I'm not sure what I was thinking, but you're quite right: this will only work with a functor, not an actual function. My apologies.

Jerry Coffin
Works great with a functor. But won't compile for a function: int echo(int i){return i;} int main(void){whatever<echo> whateverObj;return 1;}gives "error: expected a type, got ‘echo’"
academicRobot
@Jerry Coffin This was one of the first things I tried, so you'll get no criticism from me :)
academicRobot
This is the correct solution. See `std::less<T>`, which uses precisely the same pattern, and for the same reason. The direct call is why `std::sort` beats `std::qsort`.
MSalters
@MSalters no (see comment to pmr)
academicRobot
+3  A: 

If you use a function pointer type in your template and instantiate it with a fixed function, then the compiler should use a direct call for that function pointer call.

Chris Dodd
+1 Just tried it out, works great. What about accepting member functions from arbitrary class (not considering virtual functions)? Your answer gives me some ideas for this...
academicRobot
+1  A: 
#include <iostream>                                                             

template<void F()>                                                              
struct CALLER                                                                   
{                                                                               
  static void do_call()                                                         
  {                                                                             
    std::cout << __PRETTY_FUNCTION__ << std::endl;                              
    F();                                                                        
  };                                                                            
};                                                                              

void f()                                                                        
{                                                                               
  std::cout << __PRETTY_FUNCTION__ << std::endl;                                
}                                                                               

int main()                                                                      
{                                                                               
  CALLER<f>::do_call();                                                         
  return(0);                                                                    
}                                                                               
Tomek
A: 

Thought I'd share my own solution for standard functions, extended from other answers here. This uses variadic paramters as a short hand. It wouldn't be hard (just tedious) to do this as a set of N-ary templates. Interestingly, N-ary templates are more flexible for this pattern, since the nested struct would no longer be required. Compiles with g++ -std=c++0x

template <typename F>
struct caller;

template <class R, class ... A>
struct caller<R(A ...)>{
   template <R F(A ...)>
   struct func{
      R operator()(A ... args){
         return F(args ...);
      }
   };
};

which is invoked and called like this:

int echoFunc(int i) {std::cout << "echo " << i << std::endl; return i;}
...
caller<int(int)>::func<echoFunc> f;
f(1);

Without -O2 compiles to two nested immediate function calls, with -O2 the call to f(1) reduces to an immediate call to echoFunc.

This works as expected for member functions as well, with gcc>=4.5 and vs2008.

academicRobot