Created
May 22, 2019 16:44
-
-
Save ahota/c8288979c6c0054a350f07e53418f298 to your computer and use it in GitHub Desktop.
Compilable/runnable example of having main() in a namespace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <vector> | |
/************************************************************************** | |
* Example of having main() in a namespace * | |
* ----------------------------------------------------------------------- * | |
* By using extern "C", we avoid C++'s name mangling of main()'s symbol, * | |
* despite the fact that it is hidden in a bird's nest of namespaces in * | |
* our code. * | |
* Normally, it would contain semi-garbage characters that may or may not * | |
* look like the namespace(s) the symbol is contained within. * | |
* With extern "C", we get a clean reference to main that ld can link. * | |
* ----------------------------------------------------------------------- * | |
* Run with: * | |
* $ g++ main_namespace.cpp -o mn * | |
* $ ./mn * | |
* And you should see the bird forage in the orchard. * | |
* Try commenting out the extern "C". The code will compile but not link: * | |
* $ g++ -c main_namespace.cpp # succeeds * | |
* $ g++ main_namespace.o -o mn # fails * | |
* ----------------------------------------------------------------------- * | |
* Why would you do this? You really shouldn't. * | |
**************************************************************************/ | |
namespace birds | |
{ | |
enum Location { | |
HOME = 0, | |
TREE = 10, | |
ORCHARD = 20, | |
WINTER_HOME = 30 | |
}; | |
enum Status { | |
RESTING = 0, | |
FORAGING = 10, | |
BUILDING_NEST = 20, | |
LAYING_EGG = 30 | |
}; | |
class Bird { | |
public: | |
Bird(std::string &species) : species_name(species), | |
current_location(HOME), | |
current_status(RESTING) {} | |
std::string get_name() const { return this->species_name; } | |
Location get_location() const { return this->current_location; } | |
Status get_status() const { return this->current_status; } | |
void set_location(Location l) { this->current_location = l; } | |
void set_status(Status s) { this->current_status = s; } | |
private: | |
std::string species_name; | |
Location current_location; | |
Status current_status; | |
}; | |
std::ostream &operator<<(std::ostream &os, const Location &l) | |
{ | |
switch(l) { | |
case HOME: os << "at home"; break; | |
case TREE: os << "on another branch in the tree"; break; | |
case ORCHARD: os << "nearby in the orchard"; break; | |
case WINTER_HOME: os << "in another hemisphere for winter"; break; | |
default: os << "somewhere unclear"; break; | |
} | |
} | |
std::ostream &operator<<(std::ostream &os, const Status &s) | |
{ | |
switch(s) { | |
case RESTING: os << "resting"; break; | |
case FORAGING: os << "foraging"; break; | |
case BUILDING_NEST: os << "building its nest"; break; | |
case LAYING_EGG: os << "laying an egg"; break; | |
default: os << "something unclear"; break; | |
} | |
} | |
std::ostream &operator<<(std::ostream &os, const Bird *b) | |
{ | |
os << b->get_name() << " is "; | |
os << b->get_status() << " " << b->get_location(); | |
} | |
namespace nest | |
{ | |
class Nest { | |
public: | |
Nest(Bird *b) : owner(b) {} | |
bool occupied() const { return (this->owner->get_location() == HOME); } | |
Bird *get_owner() const { return this->owner; } | |
private: | |
Bird *owner; | |
}; | |
std::ostream &operator<<(std::ostream &os, const Nest *n) | |
{ | |
if(n->occupied()) { | |
os << "This nest is occupied by " << n->get_owner()->get_name(); | |
os << ", who is " << n->get_owner()->get_status() << " "; | |
os << n->get_owner()->get_location(); | |
} | |
else { | |
os << "This nest is empty"; | |
} | |
} | |
extern "C" | |
int main(int argc, char **argv) | |
{ | |
std::string american_robin("Turdus migratorius"); // unfortunate | |
Bird *b = new Bird(american_robin); | |
Nest *n = new Nest(b); | |
std::cout << n << std::endl; | |
b->set_location(ORCHARD); | |
b->set_status(FORAGING); | |
std::cout << b << std::endl; | |
std::cout << n << std::endl; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment