为什么这不能编译? (克++ - 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
}
答案 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的理由。