C++ 为什么boost::locale::date\u时间中的std::bad\u强制转换异常适用于全局对象而非本地对象?

C++ 为什么boost::locale::date\u时间中的std::bad\u强制转换异常适用于全局对象而非本地对象?,c++,boost,global,boost-date-time,boost-locale,C++,Boost,Global,Boost Date Time,Boost Locale,我在使用boost::locale::date\u时间库编写包装器类时遇到问题。具体地说,我不能从我的类创建全局对象,尽管除此之外其他一切都可以正常工作 以下是相关的示例代码: // DateTimeWrapper.h #include <boost\\locale\\date_time.hpp> #include <boost\\locale.hpp> class DateTimeWrapper { public: DateTimeWrapper();

我在使用boost::locale::date\u时间库编写包装器类时遇到问题。具体地说,我不能从我的类创建全局对象,尽管除此之外其他一切都可以正常工作

以下是相关的示例代码:

// DateTimeWrapper.h

#include <boost\\locale\\date_time.hpp>
#include <boost\\locale.hpp>

class DateTimeWrapper
{
public:
    DateTimeWrapper();
    ~DateTimeWrapper();

    // ... Other methods...

protected:

    boost::locale::date_time* m_date_time;
    static void Init_Global_Locale();
    static bool m_Global_Locale_Initialized;
};
正如您在代码中看到的,我使用静态成员来确保在第一次创建DateTimeWrapper对象时初始化全局区域设置。通常,这可以防止在创建boost::locale::date\u时间成员时引发std::bad\u cast异常。但是,当创建的第一个DateTimeWrapper对象是全局实例时,我仍然从该行收到异常

请注意,通过调试程序,我可以确认Init_Global_Locale()方法中的所有行都是在构造全局对象期间运行的。此示例代码还在同一源文件中声明了DateTimeWrapper::m_Global_Locale_在声明Global_date_time_对象之前已初始化,因此我知道这里的初始化顺序不是问题(通过使用调试器来确认)


那么,为什么代码适用于本地对象而不适用于全局对象,即使我可以看到所有代码行都以正确的顺序在两个版本中运行?

我无法重现错误(代码显示在单个TU中)

我的直觉是,您已经在另一个翻译单元中定义了void
DateTimeWrapper::Init\u Global\u Locale()
m\u Global\u Locale\u Initialized
,这使您陷入了(静态初始化顺序失败)

此外,您的类型会引发错误(使用非自有指针,而不是跟踪),这有很多复杂性。我将使用C++11的函数local static initialization编写更简单的代码:

#include <boost/locale.hpp>
#include <boost/locale/date_time.hpp>

struct EnsureLocaleBase {
    EnsureLocaleBase() { Init(); }

  private:
    static bool Init() {
        static auto const s_init = [] {
            boost::locale::generator gen;
            std::locale l = gen("");
            std::locale::global(l);
            return true;
        }();
        return s_init;
    }
};

class DateTimeWrapper : EnsureLocaleBase {
    boost::locale::date_time m_date_time;
};

DateTimeWrapper global_date_time_object;

int main() {
    DateTimeWrapper local_date_time_object;
}
#包括
#包括
结构EnsurelocalBase{
EnsureLocalBase(){Init();}
私人:
静态bool Init(){
静态自动常量s_init=[]{
boost::locale::gen生成器;
std::locale l=gen(“”);
std::locale::global(l);
返回true;
}();
返回s_init;
}
};
类DateTimeWrapper:EnsureLocaleBase{
boost::locale::date\u time m\u date\u time;
};
DateTimeWrapper全局\u日期\u时间\u对象;
int main(){
DateTimeWrapper本地\日期\时间\对象;
}

函数本地静态不受SIOF的影响,并且是线程安全初始化的。

我无法重现错误(代码显示在单个TU中)

我的直觉是,您已经在另一个翻译单元中定义了void
DateTimeWrapper::Init\u Global\u Locale()
m\u Global\u Locale\u Initialized
,这使您陷入了(静态初始化顺序失败)

此外,您的类型会引发错误(使用非自有指针,而不是跟踪),这有很多复杂性。我将使用C++11的函数local static initialization编写更简单的代码:

#include <boost/locale.hpp>
#include <boost/locale/date_time.hpp>

struct EnsureLocaleBase {
    EnsureLocaleBase() { Init(); }

  private:
    static bool Init() {
        static auto const s_init = [] {
            boost::locale::generator gen;
            std::locale l = gen("");
            std::locale::global(l);
            return true;
        }();
        return s_init;
    }
};

class DateTimeWrapper : EnsureLocaleBase {
    boost::locale::date_time m_date_time;
};

DateTimeWrapper global_date_time_object;

int main() {
    DateTimeWrapper local_date_time_object;
}
#包括
#包括
结构EnsurelocalBase{
EnsureLocalBase(){Init();}
私人:
静态bool Init(){
静态自动常量s_init=[]{
boost::locale::gen生成器;
std::locale l=gen(“”);
std::locale::global(l);
返回true;
}();
返回s_init;
}
};
类DateTimeWrapper:EnsureLocaleBase{
boost::locale::date\u time m\u date\u time;
};
DateTimeWrapper全局\u日期\u时间\u对象;
int main(){
DateTimeWrapper本地\日期\时间\对象;
}

函数本地静态不受SIOF的影响,而且是线程安全初始化的。

\include
应该是
\include
,同样,对于另一个主题:include始终使用unix风格的目录分隔符
//code>。VS在没有警告的情况下正确地处理了这个问题。下面是。上面的代码在我的机器上运行(在修复includes中的斜杠之后)。我确实需要在编译行中添加
-lboost\u system-mt-lboost\u locale-mt
(我使用Boost 1.72编译为
-std=c++17
。@MarekR我有一个只包含静态方法的助手类。其中一个方法使用静态的、固定的历史日期,我将其声明为helper类的静态成员。如果不是作为静态(即全局)成员变量,定义和使用此日期的更好方法是什么?我看到的唯一替代方法是每次调用静态方法时,在静态方法中创建一个日期的本地版本,这不仅效率低下,而且不如我所希望的那样透明(该日期将隐藏在函数中,而不是文件的顶部,在那里很容易看到或调整).
#include
应该是
#include
,对于另一个主题也是一样:在include中始终使用unix风格的目录分隔符
/
。VS在没有警告的情况下正确地处理了这个问题。下面是。上面的代码在我的机器上运行(在修复includes中的斜杠之后)。我确实需要在编译行中添加
-lboost\u system-mt-lboost\u locale-mt
(我使用Boost 1.72编译为
-std=c++17
。@MarekR我有一个只包含静态方法的助手类。其中一个方法使用静态的、固定的历史日期,我将其声明为helper类的静态成员。如果不是作为静态(即全局)成员变量,定义和使用此日期的更好方法是什么?我看到的唯一替代方法是每次调用静态方法时在静态方法中创建一个日期的本地版本,这不仅效率低下,而且不如我所希望的那样透明(该日期将隐藏在函数中,而不是文件的顶部,在那里很容易看到或调整)。