Skip to content

Instantly share code, notes, and snippets.

@ahota
Created May 22, 2019 16:44
Show Gist options
  • Save ahota/c8288979c6c0054a350f07e53418f298 to your computer and use it in GitHub Desktop.
Save ahota/c8288979c6c0054a350f07e53418f298 to your computer and use it in GitHub Desktop.
Compilable/runnable example of having main() in a namespace
#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