Last active
November 5, 2017 17:40
-
-
Save uucidl/c3c8eb99f7ce8848947929ed3f37384b to your computer and use it in GitHub Desktop.
CPP monsters
This file contains hidden or 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
#if _MSC_VER | |
#define COMPILE_MSVC 1 | |
#endif | |
#if !defined(COMPILE_MSVC) | |
#define COMPILE_MSVC 0 | |
#endif | |
namespace uu_monsters | |
{ | |
#if PREDECLARE | |
int some(); | |
#endif | |
class Monster1 | |
{ | |
public: | |
// If this function's prototype has not been declared proper in the namespace, | |
// then the function `some` cannot be called, although it will prevent re-declaration | |
// in this namespace. | |
// | |
// @cpp_standard{ | |
// 11.3.7: A friend function defined in a class is in the (lexical) scope of the | |
// class in which it is defined. A friend function defined outside the class is not (3.4.1). | |
// } | |
// @see: COMPILE_ERROR_A | |
// @see: COMPILE_ERROR_B | |
friend int some() { return 42; } | |
#if COMPILE_MSVC | |
// MSVC happily compiles this, and allows you to call the monster | |
// this won't work on GCC/Clang/ICC | |
static int call_some() { | |
auto ptr = some; | |
return ptr(); | |
} | |
#endif | |
#if COMPILE_ERROR_C | |
static int call_some1() { | |
// this does not work: | |
return some(); | |
} | |
#endif | |
static int call_some2() { | |
// however redeclaring works: | |
int some(); | |
return some(); | |
} | |
}; | |
#if COMPILE_ERROR_A | |
// does not compile, because it would clash with `some` in the same namespace | |
// uu_monster.cpp(xx): error C2084: function 'int uu_monsters::some(void)' already has a body | |
// uu_monster.cpp(yy): note: see previous definition of 'some' | |
int some() { | |
return 24; | |
} | |
#endif | |
} // namespace uu_monster | |
int main(int, char**) | |
{ | |
#if PREDECLARE | |
return uu_monsters::some(); | |
#endif | |
#if COMPILE_ERROR_B | |
// uu_monster.cpp(zz): error C3861: 'some': identifier not found | |
// uu_monster.cpp(zz): error C2672: 'uu_monsters::some': no matching overloaded function found | |
return uu_monsters::some(); | |
#else | |
#if COMPILE_MSVC | |
return uu_monsters::Monster1::call_some(); | |
#endif | |
#endif | |
return uu_monsters::Monster1::call_some2(); | |
} |
This file contains hidden or 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
struct Foo | |
{ | |
int a; | |
}; | |
int main(int argc, char**argv) { | |
// this looks like we're calling Foo on foo, while it's actually declaring a variable named foo! | |
// It is inherited from C, where declarations and usages are made symmetric. | |
Foo(foo); | |
foo.a = argc; | |
// See also: | |
int (a); | |
(a) = 42; | |
// One way to avoid this would be to always use the | |
// new >=c++11 syntax using braces. | |
Foo foo2{42}; | |
return foo.a; | |
} | |
// @quote{@url{http://csapp.cs.cmu.edu/3e/docs/chistory.html} | |
// For each object of such a composed type, there was already a way to mention the underlying | |
// object: index the array, call the function, use the indirection operator on the pointer. | |
// Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax | |
// in which the names typically appear. Thus, | |
// | |
// int i, *pi, **ppi; | |
// declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of | |
// these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used | |
// in an expression. Similarly, | |
// int f(), *f(), (*f)(); | |
// } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment