Thread: How do I avoid the global here ?

  1. #1
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657

    How do I avoid the global here ?

    Code:
    namespace mm
    {
    
        static std::vector<std::string> result;
        
        static int get_table_names_cb(void *NotUsed, int argc, char **argv, char **col)
        {
            for(int i=0; i<argc; ++i)
                result.push_back((argv[i] ? argv[i] : "NULL"));
            return 0;
        }
        
        std::vector<std::string> getTableNames(Database& db)
        {
            std::string command="select name from sqlite_master where type = \"table\";";
            db(command,get_table_names_cb);
            std::vector<std::string> ret;
            std::swap(ret,result);
            return ret;
        }
    
    }
    Even if I used lambda captures (which I can not because the API must take function pointers), the problem would still remain.

    Is there a good alternative when dealing with callbacks like this?

  2. #2
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Wait, why doesn't passing as a reference work here?

  3. #3
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    Many APIs that take callbacks would allow you to pass in a "private user data" void pointer that will get passed along to your callback function. It's kind of like a way to emulate lambda capture, but has existed long before C++11.

    If it doesn't, I don't think there's much you can do.

  4. #4
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Thanks, that void* was that private argument.
    Code:
        static int get_table_names_cb(void *vec, int argc, char **argv, char **col)
        {
            auto result =static_cast<std::vector<std::string>*>(vec);
            for(int i=0; i<argc; ++i)
                result->push_back((argv[i] ? argv[i] : "NULL"));
            return 0;
        }
        
        std::vector<std::string> getTableNames(Database& db)
        {
            std::string command="select name from sqlite_master where type = \"table\";";
            std::vector<std::string> ret;
            db(command,get_table_names_cb,&ret);
            return ret;
        }
    Looks un-C++ish...but works.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    technically that's not global. that's namespace-local. having variables in a namespace like that is generally considered acceptable, because they're grouped in a place where things can't automatically see them polluting the global namespace.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Elkvis
    technically that's not global. that's namespace-local. having variables in a namespace like that is generally considered acceptable, because they're grouped in a place where things can't automatically see them polluting the global namespace.
    The issue with global variables is more than just the risk of name collision. It includes the problems associated with global state, and this does not change with the introduction of a namespace.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Looks un-C++ish...but works.
    O_o

    I make such cases more "C++ish" by wrapping the API layer with a version of `Boost::Any'; the difference isn't very big, but you can do a lot of "firewall" stuff with a tool like `Boost::Any' so that you don't have to repeat yourself.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  8. #8
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by manasij7479 View Post
    Looks un-C++ish...but works.
    That's because callback function pointers are a C idiom. In C++ an API can use templates to be more typesafe and fast, though often with a penalty in code size.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to avoid rounding?
    By Eldente in forum C Programming
    Replies: 4
    Last Post: 01-27-2011, 02:22 PM
  2. Global Access to Global Class without so many pointers
    By parad0x13 in forum C++ Programming
    Replies: 1
    Last Post: 11-11-2009, 02:48 PM
  3. static global & global variables
    By aqeel in forum C Programming
    Replies: 1
    Last Post: 09-25-2009, 12:32 PM
  4. Best way to avoid using global variables
    By Canadian0469 in forum C++ Programming
    Replies: 7
    Last Post: 12-18-2008, 12:02 PM
  5. How to avoid gibberish?
    By duffmckagan in forum C Programming
    Replies: 8
    Last Post: 06-24-2006, 10:53 AM