【发布时间】:2010-10-23 18:01:49
【问题描述】:
请考虑以下代码:
template<typename T>
char (&f(T[1]))[1];
template<typename T>
char (&f(...))[2];
int main() { char c[sizeof(f<void()>(0)) == 2]; }
我预计它会执行 SFINAE 并选择第二个重载,因为将 T 替换为 T[1] 会产生
void [1]()
当然,这是一个无效的类型。参数类型(数组->指针)的调整是在将模板参数替换为函数参数并检查有效的结果类型(如 14.8.2 [temp.deduct] 描述的)之后完成的。
但是 comeau 和 GCC 都无法编译上述内容。两者都有不同的诊断。
科莫说:
“ComeauTest.c”,第 2 行:错误:不允许使用函数数组
char (&f(T[1]))[1];
GCC 说(版本4.3.3):
错误:ISO C++ 禁止零大小数组
c
意思是,GCC 没有替换失败,但是它选择了f 的第一个重载,返回一个为 1 的 sizeof,而不是像 Comeau 那样没有替换它。
什么编译器是正确的,我的代码是否有效?请在您的答案中参考或引用适当的标准部分。谢谢!
更新:标准本身在14.8.2/2 的列表中包含这样一个示例。我不知道,为什么我先忽略了它:
template <class T> int f(T[5]);
int I = f<int>(0);
int j = f<void>(0); // invalid array
虽然该示例只是提供信息,但它显示了所有这些神秘段落的意图,并且似乎表明上面的代码应该可以工作并拒绝第一次重载。
【问题讨论】:
-
litb 要求标准说明是矛盾的 :)
-
我在 usenet 上问过同样的问题,但也在这里发布了这个问题,以便可以在 SO 上存档,人们在 SO 上搜索时会找到它。使用网链接:groups.google.com/group/comp.lang.c++.moderated/browse_thread/…
-
我认为 litb 是标准...?
-
好吧,至少快速浏览一下标准可以证实 Comeau 的抱怨。根据 8.3.4,不允许使用函数数组。我只是略读了你的代码(有点匆忙的atm),所以我完全有可能错过了一些重要的东西;)
-
我想我会等待 litb 回答这个问题...
标签: c++ arrays templates sfinae