Я решил обойти ошибку в GNU libstdc ++, обратившись к внутренней переменной.Вспоминая, что Йоханнес решил эту проблему в своем блоге, я проверил это… но не смог понять код, кроме основной концепции получения статического инициализатора для грязной работы.Итак, я сводил это к этому, что довольно компактно.
Но, как уже отмечалось, это приводит к тому, что небольшие объекты и функции доступа дублируются на единицу перевода, вызывая неприятный каскад.Есть ли канонический способ сделать это, скажем, лучший метод Boost?
Извиняюсь за плохой юмор, но это не даром ... мы бы не хотели, чтобы этот код был "безопасным для работы"!
/* This hack installs a static initializer, so to avoid the ordering fiasco,
make one fresh copy per translation unit, via anonymous namespace. */
namespace {
template< typename T, T value, T &dest >
struct class_rape {
class_rape() { dest = value; } // you've been raped in the class!
static class_rape r;
};
template< typename T, T value, T &dest >
class_rape< T, value, dest > class_rape< T, value, dest >::r;
// Usage (cvt_[w]filebuf is a specialization of GCC basic_filebuf)
typedef bool cvt_filebuf::*cvt_fb_reading_t;
typedef bool cvt_wfilebuf::*cvt_wfb_reading_t;
/* Access these variables, or functions accessing them (applies recursively),
only in anonymous namespace or in non-header file, per one-definition rule. */
cvt_fb_reading_t cvt_filebuf_reading;
cvt_wfb_reading_t cvt_wfilebuf_reading;
template struct class_rape
< cvt_fb_reading_t, &cvt_filebuf::_M_reading, cvt_filebuf_reading >;
template struct class_rape
< cvt_wfb_reading_t, &cvt_wfilebuf::_M_reading, cvt_wfilebuf_reading >;
}
Кстати, вот контекст: http://pastie.org/1188625.
Обновление
Я решил проблему с дублированием в своем ответе ниже.Так что теперь я заинтересован в детерминированном, четко определенном решении, которое не включает редактирование какого-либо целевого кода и позволяет одновременно взламывать несколько специализаций шаблона.(Для данного хака требуется новая реализация для каждой целевой специализации шаблона.)