Мы используем компилятор Intel 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());
}
основной.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
объединяются, и становится лотереей, которая выбрана
# icpc a2.cc a1.cc main.cc -o main
# ./main
1 != 1
Буду признателен за помощь. Возможно, это на самом деле ошибка компилятора, и о ней уже сообщалось?
struct A
, например.struct B
? - person m.s.   schedule 21.10.2015f
не нарушает ODR? Что произойдет, если вы поместите два определенияf
в соответствующие им локальные пространства имен, чтобы исправить нарушение ODR? - person MSalters   schedule 21.10.2015boost::function<int()> f(MyTuLocalFunctor());
, и он случайным образом заменяет поведение одного функтора .cc поведением другого функтора .cc. И оказалось, что причина в том, что он объединяет статические локальные переменные, которые boost::function использует для внутренней реализации стирания своего типа. - person Johannes Schaub - litb   schedule 21.10.2015f<T>
не встроены вf1
иf2
(возможно, с__attribute__((noinline))
), вы сможете увидеть, имеют ли эти экземпляры одно и то же искажение имени или нет. Согласно Itanium C++ ABI, изменение имени области видимости функции включает в себя изменение имени функции, и я определенно ожидаю, что два экземпляра будут иметь разное изменение имени. Я подозреваю, что у icpc есть ошибка в наличии инлайнинга. - person John Calsbeek   schedule 21.10.2015f<A#1>
иf<A#2>
потребуются разные изменения, даже если они были созданы из одного и того же шаблона. Даже если в этом примере есть нарушение ODR (что, вероятно, есть), я ожидаю, что искажение имен двух статических данных будет другим. - person John Calsbeek   schedule 21.10.2015x
использовать константу или перечисление, определенные по-разному в каждой версииA
. Слабая связь статики имеет смысл, потому что она должна быть объединена с другими копиями того же экземпляра, но это несовместимо с именем, которое не искажено, чтобы содержать идентификатор безымянного пространства имен. - person John Calsbeek   schedule 21.10.2015f
в глобальном пространстве имен с разной последовательностью токенов в их определениях? Я не думаю, что буква закона об ODR заботится о связи в этом случае. - person John Calsbeek   schedule 21.10.2015