c ++模板函数的地址

时间:2010-09-04 09:31:47

标签: c++ templates function-pointers c++11

为什么这不能编译? (克++ - 4.5)

template < typename U >
static void h () {
}

int main () {
  auto p = &h<int>; // error: p has incomplete type
}

编辑:这是一个解决方法:

template < typename U >
static void h () {
}

int main () {
  typedef decltype (&h<int>) D;
  D p = &h<int>; // works
}

3 个答案:

答案 0 :(得分:13)

在C ++ 0x中,这可以保证正常工作。然而,在C ++ 03中,这不起作用(初始化部分,即),并且一些编译器显然还不支持它。

此外,我记得C ++ 0x的措辞并不清楚&h<int>当它是函数模板的参数并且推导出相应的参数时会发生什么(这是auto是什么从概念上翻译成。但是,它的意图是有效的。见this defect report他们设计措辞的地方,“Nico Josuttis”的例子及其最后的例子。

还有另一条规则,即措辞强制执行,但编译器未正确实施。例如,see this clang PR

答案 1 :(得分:0)

它不能编译,因为编译器不知道'p'的类型,这是C ++必须的,与其他语言不同。

尝试

template < typename U > 
static void h () { 
} 

int main () { 
  auto void (*p)() = &h<int>; 
} 

答案 2 :(得分:0)

尝试

 auto p  = static_cast<void(*)()>(& h<int>);

因为gcc将模板化函数视为重载函数。从gcc的角度来看,就像你有h(int param)h(float param) - 编译器必须选择哪一个?

我注意到旧版gcc中的问题是什么,但我会尝试更详细地解释它。 GCC无法推断出类型,因为模板化函数被视为过载函数。这基本上就像你会有以下内容:

void h(int)
{
}

void h(float)
{
}

void (*p)(int) = & h;  //ok
void (*p)(float) = & h; //ok
auto p = & h; //error: which version of h?

对于gcc h<int>就像重载h函数一样,具有无穷无尽的替代功能,具体取决于T参数。根据提供的代码,它是O.K.做以下事情:

void (*p)() = & h<int>;

(这就是为什么我没有得到typedefed“解决方法”)

我认为OP想要使用标签建议的c ++ 11 auto关键字,我将h<int>静态转换为void(*)(),这是一种无操作,只是欺骗gcc,因为它无法正确处理模板化函数和auto

函数void h<int>()void h<float>()当然应该被视为具有相同指针类型的不同函数,而不是h函数的重载版本。在实例化时,它们的行为应该像void hInt()void hFloat(),您应该可以像这样使用自动:

void hInt()
{
}

void hFloat()
{
}

auto p = hInt;
p = hFloat;

但由于某些原因,gcc就像h的重载版本。

请给出downvotes的理由。