Reputation: 6107
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?
Upvotes: 6
Views: 468
Reputation: 1679
It's also possible to pass a function reference to a template. This compiles in the latest clang (3.2) and prints "Hello World!" as you'd expect:
template<void(& f)()> struct test {
void operator()() {
f();
}
};
void foo() {
std::cout << "Hello World!\n";
}
test<foo> bar;
int main() {
bar();
}
I'm not sure if this'll really make a difference compared to using a function pointer, though.
Upvotes: 0
Reputation: 6107
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.
Upvotes: 0
Reputation: 4659
#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);
}
Upvotes: 1
Reputation: 490418
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.
Upvotes: 0
Reputation: 126418
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.
Upvotes: 3
Reputation: 57729
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.
Upvotes: 0
Reputation: 17853
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?
Upvotes: 1