【发布时间】:2016-01-20 15:26:57
【问题描述】:
我们使用英特尔 C++ 编译器并检测到它错误编译 (?) 以下内容,从使用 boost::function<Ponies()> f(unnamedNamespacedFunctor) 减少。
a1.cc:
template<typename T>
int f(T) { static int x = T::x; return x; }
namespace { struct A { static const int x = 1; }; }
int f1() {
return f(A());
}
a2.cc:
template<typename T>
int f(T) { static int x = T::x; return x; }
namespace { struct A { static const int x = 0; }; }
int f2() {
return f(A());
}
main.cc:
#include <cstdio>
int f1();
int f2();
int main() {
std::printf("%d != %d\n", f1(), f2());
}
命令行:
# icpc a1.cc a2.cc main.cc -o main
# ./main
0 != 0
我的问题是:这符合要求吗?在这种实例化中使用静态局部变量会产生未定义的行为吗?在检查生成的符号时,我注意到虽然f 具有本地链接,但正如我所怀疑的那样,x 静态变量接收弱链接,因此两个x'es 被合并,它变成了被选中的彩票
# icpc a2.cc a1.cc main.cc -o main
# ./main
1 != 1
我将不胜感激。也许这毕竟是一个编译器错误并且已经被报告了?
【问题讨论】:
-
如果您将
struct A之一重命名为例如struct B? -
f的定义不是违反了ODR吗?如果您将f的两个定义放在它们各自的本地命名空间中以修复 ODR 违规,会发生什么? -
@MSalters 对于 boost::function 也是如此,我无法轻易更改它:) 如果它违反了 ODR,我想这违反了现有做法。我还没有找到禁止这个的规则。函数模板实例化的链接是外部的,但参数类型具有内部链接(因此在不同的 TU 中是不同的类型!)。我找不到禁止它的段落,我不确定是否有禁止它的理由。
-
@JohannesSchaub-litb:您如何最终得到 Boost.function 的两个定义?宏? ODR主要是说token序列必须相同,当然token含义在实例化后可能会有所不同。毕竟,这就是模板的全部意义所在。
-
@MSalters 我只是创建了一个
boost::function<int()> f(MyTuLocalFunctor());,它随机地将一个.cc 仿函数的行为替换为另一个.cc 仿函数的行为。事实证明,原因是它合并了静态局部变量,boost::function 使用它在内部实现其类型擦除。
标签: c++ templates static undefined-behavior icc