To force data into an initialized data segment when available on OS X and Linux (but not GNU Hurd), perform the following. Note that this technique is platform specific, but it side steps C/C++ limitations on visibility and storage classes.
#if defined(__clang__ ) && !defined(__apple_build_version__)
#define LLVM_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#elif defined(__clang__ ) && defined(__apple_build_version__)
#define APPLE_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#elif defined(__GNUC__)
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
...
#if ((__MACH__ >= 1) && ((LLVM_CLANG_VERSION >= 30600) || (APPLE_CLANG_VERSION >= 70100) || (GCC_VERSION >= 40300)))
#define INIT_SECTION __attribute__((section ("__DATA,__data")))
#elif ((__ELF__ >= 1) && (GCC_VERSION >= 40300))
#define INIT_SECTION __attribute__((section ("nocommon")))
#else
#define INIT_SECTION
#endif
foo.h:
extern bool g_x;
extern bool g_y;
foo.cpp:
bool INIT_SECTION g_x, INIT_SECTION g_y;
I'm still working on the compiler version numbers, so they may not be as accurate as they could be. They tested OK under LLVM Clang, Apple Clang, GCC, and MacPorts GCC. But I suspect Clang will be able to move down, and GCC may need to move up.