在多个共享库的情况下,如何仅创建 class 模板静态成员的一个实例?

How to make one instance only of class template static member in case of several shared libraries?

我有一个带有静态成员的模板 class,为简单起见:

template<typename T>
struct A
{
    static inline int x = 1;
};

但是如果我在几个 shared-libraries 中包含 header 和 struct A 定义,它们中的每一个都会有自己的 A<T>::x 实例。而且我希望仅在某个共享库和访问它的所有其他库中拥有 A<T>::x 的实例(对于某些固定的 T 类型列表)。

在Visual Studio中我可以在header

中写
#ifdef _WIN32
#   ifdef MY_LIB_EXPORT
#       define MY_LIB_API __declspec(dllexport)
#   else
#       define MY_LIB_API __declspec(dllimport)
#   endif
#else
#       define MY_LIB_API
#endif

template<typename T>
struct A
{
    MY_LIB_API static int x;
};

并在来自所选动态库的 .cpp-file 中:

template<> int A<SpecificType1>::x = 0;
template<> int A<SpecificType2>::x = 0;
…

但不幸的是,这种方式不适用于 linux/clang,在其他 .cpp-files 中我得到:

error: instantiation of variable 'A<SpecificType1>::x' required here, but no definition is available

是否有解决我的任务的通用方法?

对于 GCC,您可以使用:

#define EXPORT __attribute__((visibility("default")))

我已经使用 CMake 使用以下设置对其进行了测试 mylib.h:

#define EXPORT __attribute__((visibility("default")))

template<typename T>
struct A
{
  EXPORT static int x;
};

mylib.cpp

#include "mylib.h"

template<> int A<int>::x = 1;
template<> int A<bool>::x = false;

main.cpp

std::cout << "A<int>: " << A<int>::x << std::endl;
std::cout << "A<bool>: " << A<bool>::x << std::endl;

输出:

A<int>: 1
A<bool>: 0

CMakeLists.txt

# Change the default to hidden, then you need to explicitly set it
# Thus, normally, you shouldn't have the problem
add_compile_options(-fvisibility=hidden) # only for testing the EXPORT define

add_library(mylib SHARED mylib.cpp)
add_executable(example main.cpp main2.cpp) # Main2 also used mylib
target_link_libraries(example mylib)

因此,对于通用选项,我建议将此定义添加到您的 if else define 宏列表中。