sizeof和function template:sizeof(&amp; f)vs sizeof(&amp; f <int>)

时间:2016-09-04 17:42:35

标签: c++ templates gcc clang language-lawyer

正如[5.3.3/3] expr.sizeof ,工作草案)所述:

  

sizeof运算符可以应用于指向函数的指针,但不能直接应用于函数。

以下最小的工作示例编译良好:

void f() { }

int main() {
    sizeof(&f);
}

我希望下面的那个也能奏效:

template<typename T>
void f() { }

int main() {
    sizeof(&f<int>);
}

无论如何,即使它与clang(v3.8)编译,它也不使用GCC(v6.1)。
错误是:

  

错误:没有上下文类型信息的重载函数的地址

我怀疑这是GCC的错误(如果确认,我会打开一张票) 我是对的,还是我在这里遗漏了一些东西,GCC确实是对的?

与此同时,我向GCC开了an issue

1 个答案:

答案 0 :(得分:2)

这是一个错误。以下代码编译良好:

template<typename T>
void f() { }

int main() {
    auto fptr = &f<int>;
    return sizeof(fptr);
}

请注意,起初我没有认真阅读这个问题。我的印象是函数f<int>确实超载了,例如如下:

template<typename T>
void f() { }

template<typename T>
void f(T) { }

int main() {
    sizeof(&f<int>);
}

在这样的问题阅读中,我准备了以下答案,我仍然想与社区分享:

我不会将其视为错误。

将其限定为错误的论点如下 - 所有函数指针都具有相同的大小,那么为什么sizeof运算符中的函数意味着什么呢?

我打算打败这个论点。

首先,它从错误的前提出发。 C ++标准只保证

  

将“指向T1的指针”的prvalue转换为“指向的指针”   T2“(其中T1T2是函数类型)并返回其原始类型会产生原始指针值

并不一定意味着指向不同类型函数的指针的大小是相同的。但我承认,在实践中这是真的。

接下来,即使我们接受论证背后的前提和逻辑,那么我们也必须接受以下程序也应该编译而没有任何问题的说法:

template<typename T>
void f() { }

template<typename T>
void f(T) { }

int main() {
    auto fptr = &f<int>;
    return sizeof(fptr);
    // fptr is not used anywhere else, so the compiler must not
    // whine about the ambiguity on its declaration line
}

继续以这种方式,我们认为编译模糊不应该被报告,只要它们被后续代码消除。