【问题标题】:Define a static variable in header only using macro仅使用宏在标头中定义静态变量
【发布时间】:2017-08-12 17:43:50
【问题描述】:

我的目标是能够仅在标头中创建一个静态变量,该变量将使用我提供的值在.cpp 文件中为我初始化它。它应该看起来像这样:

struct UserDefaults {
    STATIC(bool, isFullscreen, true)
    STATIC(bool, isBorderless, false)
    STATIC(std::string, profileName, "") 
}

等于:

// .hpp file
struct UserDefaults {
    static bool isFullscreen;
    static bool isBorderless;
    static std::string profileName;
}

// .cpp file
bool UserDefaults::isFullscreen = true;
bool UserDefaults::isBorderless= false;
std::string UserDefaults::profileName = "";

我查看了How to have static data members in a header-only library?,但无法将 Pesche 的解决方案应用于我的案例。

【问题讨论】:

  • 单个宏无法实现这种分离。您需要使用在编译之前运行的预处理脚本来分析源代码并生成此类代码。
  • 似乎我听到了一个与几年前类似的话题的讨论,最终结果是决定使用静态成员函数......该函数有一个返回引用的成员变量。 ..模板也可能是一种方法...
  • @RemyLebeau 我知道没有单一的宏解决方案。我尝试使用我发布的问题中的模板以某种方式使用该解决方案,并创建用于初始化、读取和写入的宏。
  • 宏只会使混淆代码变得不可调试且不可读。你不能再敲击键盘 20 次吗?

标签: c++ c++11 static macros


【解决方案1】:
#include <iostream>

#define STATIC(type, name, value) \
    static type& name() { static type ret = value; return ret; }

struct UserDefaults
{
     STATIC(bool, isFullscreen, true)
     STATIC(bool, isBorderless, false)
     STATIC(std::string, profileName, "")
};

int main()
{
    UserDefaults ud;

    std::cout << ud.isFullscreen() << " " << ud.isBorderless() << " " << ud.profileName() << std::endl;
}

输出

1 0 

【讨论】:

  • 为什么isFullscreen int 不是bool
  • 我使用的正是您建议的,但问题是您不能写入该值,只能从中读取。我需要它是一个静态变量。
  • @Maroš Beťko:仔细看!这些静态函数返回对它们内部静态变量的引用,因此您可以分配给它们。
【解决方案2】:

为什么要使用宏?这是 c++。

#include <string>
#include <iostream>

template<class Type, Type(*init)()>
struct static_thing
{
    using value_type = Type;

    operator value_type&() const {
        return get();
    }

    static value_type& get() {
        static value_type _ { init() };
        return _;
    }

    /*
     * add whatever operations you need
     */

     template<class Source>
     value_type& operator=(Source&& value) {
        get() = std::forward<Source>(value);
     }

     friend auto operator<<(std::ostream& os, static_thing const& st) -> std::ostream&
     {
         return os << st.get();
     }
};

inline bool make_true() { return true; }
inline bool make_false() { return true; }
inline std::string empty_string() { return std::string(); }



struct UserDefaults
{

    static_thing<bool, make_true> isFullscreen;
    static_thing<bool, make_false> isBorderless;
    static_thing<std::string, empty_string> profileName;
};


int main()
{
    auto defs = UserDefaults();

    defs.profileName = "foo";

    std::cout << defs.profileName << " " << defs.isFullscreen << std::endl;

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 2013-08-04
    • 2016-06-08
    • 1970-01-01
    • 2016-11-08
    • 2018-12-10
    • 1970-01-01
    相关资源
    最近更新 更多