为未定义函数选择正确重载的编译器差异
Compiler differences on choosing the right overload for undefined function
让我们有以下代码:
//template <typename ... A>
//void foo(char a, A ... args);
template <typename T> void P(T x) { std::cout << x << ' '; }
void foo(char a) { P(3); P(a); }
template <typename ... A>
void foo(int a, A ... args)
{
foo(args...);
P(a);
}
template <typename ... A>
void foo(char a, A ... args)
{
P(a);
foo(args...);
}
int main()
{
foo('1', '2', 48, '4', '5');
}
它在 MSVC2015 和 ideone's GCC
上的行为不同
当args...
等于48, '4', '5'
时,调用foo
。编译器因调用 foo
而异。 MSVC 考虑了在实际调用中定义的重载(之前没有声明),而 GCC 只适用于已经声明的重载。如果我取消注释声明,MSVC 和 GCC 都会打印 1 2 4 3 5 48
。如果声明被注释掉,MSVC 打印相同,但 GCC 打印 1 2 3 5 52 48
(52 is ascii for 4)
哪个编译器符合标准?
我有 n4296 草稿,但我在那里找不到答案,该文件对我来说有点不可读...
MSVC 未能按照标准规定为模板实施 two phase name lookup。此编译器错误地将所有名称解析推迟到模板 instantiation.
点
其他编译器在模板定义 处正确解析非依赖名称。这就是您观察到的差异的原因。在定义点,第二个 foo
模板是不可见的,因此符合规范的编译器无法使用它。但在实例化时,它是可见的,MSVC 很高兴地找到了它。
让我们有以下代码:
//template <typename ... A>
//void foo(char a, A ... args);
template <typename T> void P(T x) { std::cout << x << ' '; }
void foo(char a) { P(3); P(a); }
template <typename ... A>
void foo(int a, A ... args)
{
foo(args...);
P(a);
}
template <typename ... A>
void foo(char a, A ... args)
{
P(a);
foo(args...);
}
int main()
{
foo('1', '2', 48, '4', '5');
}
它在 MSVC2015 和 ideone's GCC
上的行为不同当args...
等于48, '4', '5'
时,调用foo
。编译器因调用 foo
而异。 MSVC 考虑了在实际调用中定义的重载(之前没有声明),而 GCC 只适用于已经声明的重载。如果我取消注释声明,MSVC 和 GCC 都会打印 1 2 4 3 5 48
。如果声明被注释掉,MSVC 打印相同,但 GCC 打印 1 2 3 5 52 48
(52 is ascii for 4)
哪个编译器符合标准?
我有 n4296 草稿,但我在那里找不到答案,该文件对我来说有点不可读...
MSVC 未能按照标准规定为模板实施 two phase name lookup。此编译器错误地将所有名称解析推迟到模板 instantiation.
点其他编译器在模板定义 处正确解析非依赖名称。这就是您观察到的差异的原因。在定义点,第二个 foo
模板是不可见的,因此符合规范的编译器无法使用它。但在实例化时,它是可见的,MSVC 很高兴地找到了它。