更新:经过一些额外的阅读后,我真正想要的是保证早期绑定(这应该转换为立即调用非虚函数和非PIC代码),这可以通过传递(成员)函数作为模板参数。我遇到的问题是gcc< 4.5和icc 11.1可以为成员函数指针模板参数调用生成一些时髦的指令。 AFAICT,gcc> = 4,5和vs2008可以很好地处理这些模板参数调用。
首先,也许文字不是这个概念的正确术语,但它是我能想到的最接近的(不是作为一等公民的功能意义上的文字)。
这个想法是,当你进行传统的函数调用时,它会编译成这样的东西:
callq <immediate address>
但是如果你使用函数指针进行函数调用,它会编译成这样的东西:
mov <memory location>,%rax
callq *%rax
哪一切都很好。但是,如果我正在编写一个模板库,需要使用指定的参数列表进行某种回调,并且该库的用户应该知道他们想要在编译时调用什么函数?然后我想编写我的模板以接受函数文字作为模板参数。所以,类似于
template <int int_literal>
struct my_template {...};`
我想写
template <func_literal_t func_literal>
struct my_template {...};
并在my_template中调用func_literal编译为callq <immediate address>
。
C ++中是否有设施可以实现相同的效果?如果没有,为什么不(例如一些灾难性的副作用)? C ++ 0x或其他语言怎么样?
答案 0 :(得分:3)
如果在模板中使用函数指针类型并使用固定函数对其进行实例化,则编译器应使用该函数指针调用的直接调用。
答案 1 :(得分:1)
CodeProject.com:
我在几个平台上使用过:http://www.codeproject.com/kb/cpp/FastDelegate.aspx
在搜索结果中看到,将显示为:http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx
......或者这不是你想要的东西吗?
答案 2 :(得分:1)
#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);
}
答案 3 :(得分:0)
在C ++语言中,翻译人员不会将函数名称折叠到可执行文件中,它们会丢失并永远消失。
您可以创建一个功能名称与功能地址的表格。由于C和C ++是类型信息的粘合剂,因此在汇编语言中可能更容易声明。在高级语言中,您必须为每种不同类型的函数指针创建一个表。但是,在装配中,它并不在乎。虽然您可以使用其中带有switch
的函数来返回函数指针或执行函数。
另一种方法是功能ID(枚举)与功能地址。
答案 4 :(得分:0)
至少如果我理解你的问题,这是微不足道的:
template <class func>
struct whatever {
operator()() {
func();
}
};
func();
的来电通常会在您询问时直接调用func()
,或者如果func()
很小,则其代码通常会内联生成。如果您想提高内联生成的机会,通常需要将其编写为仿函数(重载operator()
的类)而不是正常函数。作为一个普通的函数,你最常会调用实际的函数(但它将是一个直接调用,而不是通过指针调用)。
编辑:我不确定我在想什么,但你说得对:这只适用于仿函数,而不是实际函数。道歉。
答案 5 :(得分:0)
以为我会分享我自己的标准功能解决方案,这里从其他答案扩展而来。这使用可变参数作为简写。作为一组N-ary模板来做这件事并不困难(只是单调乏味)。有趣的是,N-ary模板对于此模式更灵活,因为不再需要嵌套结构。使用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 ...);
}
};
};
被调用并调用如下:
int echoFunc(int i) {std::cout << "echo " << i << std::endl; return i;}
...
caller<int(int)>::func<echoFunc> f;
f(1);
如果没有-O2
编译到两个嵌套的即时函数调用,-O2
调用f(1)
会立即调用echoFunc
。
这也适用于成员函数,gcc&gt; = 4.5和vs2008。
答案 6 :(得分:0)
也可以将函数引用传递给模板。这编译在最新的clang(3.2)中并打印“Hello World!”正如你所期望的那样:
template<void(& f)()> struct test {
void operator()() {
f();
}
};
void foo() {
std::cout << "Hello World!\n";
}
test<foo> bar;
int main() {
bar();
}
我不确定与使用函数指针相比,这是否真的会有所不同。