0

My goal is to be able to create a static variables solely in header with a macro that would take care of initializing it in a .cpp file for me with value I've provided. It should look something like this:

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

Which would be equal to:

// .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 = "";

I've looked at How to have static data members in a header-only library?, but I wasn't able to apply Pesche's solution for my case.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Maroš Beťko
  • 2,181
  • 2
  • 16
  • 42
  • 1
    There is no way a single macro can do that kind of separation. You would need to use a pre-processing script that is run prior to compiling to analyze the source and generate such code. – Remy Lebeau Aug 12 '17 at 17:50
  • It seems like I heard a discussion about a topic similar to this years ago and the end result was the decision to use static member functions...the function has a single member variable that returns a reference...templates may also be a way to do it... – Dr t Aug 12 '17 at 18:00
  • @RemyLebeau I know there isn't a single macro solution. I tried to somehow use the solution using templates from the question I posted with creating macros for initializing, reading and writing. – Maroš Beťko Aug 12 '17 at 18:29
  • macros just make obfuscated code that's un-debuggable and unreadable. Can't you just tap the keyboard 20 more times? – Richard Hodges Aug 12 '17 at 22:52

2 Answers2

3
#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;
}

Output

1 0 
kocica
  • 6,412
  • 2
  • 14
  • 35
0

Why use macros at all? This is 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;

}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142