#include <iostream>
#include <typeinfo>
// Would go into operator_auto.hpp
namespace operator_auto {
template <class T> struct operator_auto_type {
using type = T;
};
struct operator_auto_imp {
template <class T> typename operator_auto_type<T>::type operator=(T &&t) {
return std::forward<T>(t);
}
};
namespace {
operator_auto_imp _auto;
}
}
// End operator_auto.hpp
// Example adapted from http://l...content-available-to-author-only...s.com/2011/02/21/inferring-too-much/ by Motti Lanzkron
#define _CRT_SECURE_NO_WARNINGS // don't warn about strcpy in VS10
#include <cstring>
#include <iostream>
namespace my {
class string {
size_t len;
char *str;
string(char *buf, size_t buf_len) : len(buf_len), str(buf) {}
public:
explicit string(const char *src) : len(strlen(src)), str(new char[len + 1]) {
std::strcpy(str, src);
}
string(const string &other) : len(other.length()), str(new char[len + 1]) {
other.copy_to(str);
}
string &operator=(const string &other) {
if (this != &other) {
char *tmp = new char[other.len];
other.copy_to(tmp);
delete[] str;
str = tmp;
len = other.len;
}
return *this;
}
~string() { delete[] str; }
size_t length() const { return len; }
private:
void copy_to(char *buff) const { std::strcpy(buff, str); }
friend struct helper; // because you can't befriend a template
struct helper {
static void copy(const string &str, char *buf) { str.copy_to(buf); }
template <class T> static void copy(const T &t, char *buf) {
t.copy_to(buf);
}
static string create(char *buf, size_t len) { return string(buf, len); }
};
public:
template <class T> class concat {
const T &lhs;
const string &rhs;
bool valid;
public:
concat(const T &left, const string &right)
: lhs(left), rhs(right), valid(true) {}
~concat() { valid = false; }
size_t length() const { return lhs.length() + rhs.length(); }
void copy_to(char *dest) const {
if (!valid)
throw "Here there be dragons^H^H^H undefined behaviour";
helper::copy(lhs, dest);
helper::copy(rhs, dest + lhs.length());
}
operator string() const {
char *buf = new char[length() + 1];
copy_to(buf);
return helper::create(buf, length());
}
concat<concat<T> > operator+(const string &str) const {
return concat<concat<T> >(*this, str);
}
};
public:
concat<string> operator+(const string &str) const {
return concat<string>(*this, str);
}
friend std::ostream &operator<<(std::ostream &os, const string &str) {
return os << str.str;
}
};
}
namespace operator_auto {
template <class T> struct operator_auto_type<my::string::concat<T> > {
using type = my::string;
};
}
#include <vector>
#include <limits>
std::vector<bool> to_bits(unsigned int n) {
const int bits = std::numeric_limits<unsigned int>::digits;
std::vector<bool> ret(bits);
for (int i = 0, mask = 1; i < bits; ++i, mask *= 2)
ret[i] = (n & mask) != 0;
return ret;
}
namespace operator_auto {
template <> struct operator_auto_type<std::vector<bool>::reference> {
using type = bool;
};
}
void test_ref(bool &b) { std::cout << "ref\n"; }
void test_ref(const bool &b) { std::cout << "c-ref\n"; }
void test_ref(bool &&b) { std::cout << "rv-ref\n"; }
int main() {
{
using operator_auto::_auto;
my::string a("hello"), b(" "), c("world"), d("!");
auto s = _auto = a + b + c + d;
auto a1 = _auto = a;
std::cout << s << std::endl;
}
{
using operator_auto::_auto;
bool b = _auto = to_bits(42)[3];
auto a = _auto = to_bits(42)[3];
std::cout << std::boolalpha << b << std::endl;
std::cout << std::boolalpha << a << std::endl;
// This should be r-value ref
test_ref(_auto = to_bits(42)[3]);
// This should be ref
test_ref(_auto = b);
}
}