2017-08-12 2 views
0

Mon but est de pouvoir créer des variables statiques uniquement en en-tête avec une macro qui prendrait soin de l'initialiser dans un fichier .cpp pour moi avec la valeur que j'ai fournie. Il devrait ressembler à ceci:Définir une variable statique dans l'en-tête en utilisant seulement la macro

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

qui serait égal à:

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

Je l'ai regardé How to have static data members in a header-only library?, mais je ne pouvais pas appliquer la solution de Pesche pour mon cas.

+1

Une macro ne peut pas effectuer ce type de séparation. Vous devez utiliser un script de pré-traitement qui est exécuté avant la compilation pour analyser la source et générer un tel code. –

+0

Il semble que j'ai entendu une discussion sur un sujet similaire à celui d'il y a quelques années et le résultat final était la décision d'utiliser des fonctions membres statiques ... la fonction a une seule variable membre qui retourne une référence ... façon de le faire ... –

+0

@RemyLebeau Je sais qu'il n'y a pas une seule solution macro. J'ai essayé d'utiliser la solution en utilisant des modèles de la question que j'ai posté avec la création de macros pour l'initialisation, la lecture et l'écriture. Les macros –

Répondre

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

sortie

1 0 
+0

Pourquoi 'isFullscreen'' int' n'est pas 'bool'? – user463035818

+0

J'utilisais exactement ce que vous avez proposé, mais le problème est que vous ne pouvez pas écrire à cette valeur seulement en lire. J'ai besoin d'être une variable statique. –

+2

@ Maroš Beťko: regardez-le attentivement! ces fonctions statiques renvoient une référence à une variable statique à l'intérieur d'elles, donc vous pouvez leur assigner. –

0

Pourquoi utiliser des macros du tout? C'est 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; 

}