Created
March 29, 2014 19:54
-
-
Save rianhunter/9861720 to your computer and use it in GitHub Desktop.
C++ compilers can manipulate and create string literals at compile time
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 <type_traits> | |
#include <cstring> | |
#include <cstdio> | |
template <size_t N> | |
class StaticallySizedString { | |
char _str[N + 1]; | |
public: | |
template <size_t a_size, size_t b_size, | |
typename std::enable_if<a_size + b_size == N>::type * = nullptr> | |
StaticallySizedString(const StaticallySizedString<a_size> & a, | |
const StaticallySizedString<b_size> & b) { | |
std::memcpy(_str, a.c_str(), a_size); | |
std::memcpy((char *) _str + a_size, b.c_str(), b_size); | |
_str[a_size + b_size] = '\0'; | |
} | |
StaticallySizedString(const char *f) { | |
std::memcpy(_str, f, sizeof(_str)); | |
} | |
template <size_t other_n> | |
StaticallySizedString<N + other_n> | |
operator+(const StaticallySizedString<other_n> & other) const { | |
return StaticallySizedString<N + other_n>(*this, other); | |
} | |
const char *c_str() const { | |
return _str; | |
} | |
}; | |
template <size_t N> | |
StaticallySizedString<N - 1> | |
make_static_string(const char (&str)[N]) { | |
return StaticallySizedString<N - 1>(str); | |
} | |
int main(int argc, char *argv[]) { | |
// because StaticallySizedString's storage is known at compile time | |
// (it's not a pointer to malloc'd memory) | |
// the following will be run at compile-time | |
// (does not work with std::string) | |
auto hai = make_static_string("abbb") + make_static_string("b"); | |
// this would fail: | |
// make_static_string(argv[0]) | |
std::printf("%s\n", hai.c_str()); | |
return 0; | |
} | |
/* | |
$ g++ -v | |
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) | |
Target: x86_64-apple-darwin13.0.0 | |
Thread model: posix | |
$ g++ -std=c++11 -O3 -S test.cc | |
$ cat test.s | |
.section __TEXT,__text,regular,pure_instructions | |
.globl _main | |
.align 4, 0x90 | |
_main: ## @main | |
.cfi_startproc | |
## BB#0: | |
pushq %rbp | |
Ltmp2: | |
.cfi_def_cfa_offset 16 | |
Ltmp3: | |
.cfi_offset %rbp, -16 | |
movq %rsp, %rbp | |
Ltmp4: | |
.cfi_def_cfa_register %rbp | |
subq $16, %rsp | |
movw $98, -4(%rbp) | |
movl $1650614881, -8(%rbp) ## imm = 0x62626261 | |
leaq -8(%rbp), %rdi | |
callq _puts | |
xorl %eax, %eax | |
addq $16, %rsp | |
popq %rbp | |
ret | |
.cfi_endproc | |
.subsections_via_symbols | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment