#include <cstdio>
#include <iostream>
#include <string>
#include <type_traits>
#include <sstream>
#include <functional>
namespace safe
{
namespace detail
{
// No default. Everything should either be a basic_string or a
// scalar. If something else gets by, this will fail to compile here
template<typename T, typename Enable = void>
struct remove_string;
// Handles scalars (primatives + pointers) by simply returning the input.
// will be optimized out.
template<typename T>
struct remove_string<T, typename std::enable_if<std::is_scalar<T>::value>::type>
{
static T convert(T val)
{
return val;
}
};
// Handles basic strings by returning their c_str()
template<typename Char, typename Traits>
struct remove_string<std::basic_string<Char, Traits>, void>
{
typedef std::basic_string<Char, Traits> string_type;
static auto convert(const string_type& val) -> decltype(val.c_str())
{
return val.c_str();
}
};
// Default, resort to stringstream to return a string for the value
template<typename T, typename Enable = void>
struct remove_object
{
static std::string convert(const T& val)
{
std::ostringstream s;
s << val;
return s.str();
}
};
// For primatives + pointers, just forward. Note, the decay used earlier
// causes arrays to decay to pointers and use this.
template<typename T>
struct remove_object<T, typename std::enable_if<std::is_scalar<T>::value>::type>
{
static T convert(T val)
{
return val;
}
};
// For std::basic_string, just simply forward the reference, not copy is needed
template<typename Char, typename Traits>
struct remove_object<std::basic_string<Char, Traits>, void>
{
typedef std::basic_string<Char, Traits> string_type;
static const string_type& convert(const string_type& val)
{
return val;
}
};
// For reference wrappers, unwrap the reference, and then decay it and return
// whatever that would return.
template<typename T>
struct remove_object<std::reference_wrapper<T>, void >
{
typedef remove_object< typename std::decay<T>::type > sub_call;
static auto convert(std::reference_wrapper<T> const& ref) -> decltype(sub_call::convert(ref.get()))
{
return sub_call::convert(ref.get());
}
};
template<typename ... Args>
int printf(const char* fmt, const Args&... args)
{
//std::cout << __PRETTY_FUNCTION__ << std::endl;
return std::printf(fmt, remove_string<typename std::decay<const Args&>::type >::convert(args)...);
}
}
template<typename ... Args>
int printf(const char* fmt, const Args&... args)
{
//std::cout << __PRETTY_FUNCTION__ << std::endl;
return detail::printf(fmt, detail::remove_object<typename std::decay<const Args&>::type>::convert(args)...);
}
template<typename ... Args>
int printf(const std::string& fmt, const Args&... args)
{
return printf(fmt.c_str(), args...);
}
}
struct X
{
int i;
explicit X(int i) :
i(i)
{
}
};
std::ostream& operator <<(std::ostream& str, const X& x)
{
str << "X(" << x.i << ")";
return str;
}
int main()
{
const std::string h("Hello");
char w[] = "World";
const char* t = "There!";
char* w2 = w;
int i = 10;
X x(456);
using safe::printf;
printf("%s %s %s %s %d %s, %s %f\n", h, w, t, std::string("Temp"), i, x, "foo", 0.12345);
printf(std::string("%s %s %s\n"), "More fun!", x, w2);
printf("Ref Test: %s %s %s\n", std::ref(w), std::ref(h), std::cref(x));
}
I2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDxzc3RyZWFtPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KbmFtZXNwYWNlIHNhZmUKewogICAgbmFtZXNwYWNlIGRldGFpbAogICAgewogICAgICAgIC8vIE5vIGRlZmF1bHQuICBFdmVyeXRoaW5nIHNob3VsZCBlaXRoZXIgYmUgYSBiYXNpY19zdHJpbmcgb3IgYQogICAgICAgIC8vIHNjYWxhci4gIElmIHNvbWV0aGluZyBlbHNlIGdldHMgYnksIHRoaXMgd2lsbCBmYWlsIHRvIGNvbXBpbGUgaGVyZQogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIEVuYWJsZSA9IHZvaWQ+CiAgICAgICAgc3RydWN0IHJlbW92ZV9zdHJpbmc7CgogICAgICAgIC8vIEhhbmRsZXMgc2NhbGFycyAocHJpbWF0aXZlcyArIHBvaW50ZXJzKSBieSBzaW1wbHkgcmV0dXJuaW5nIHRoZSBpbnB1dC4KICAgICAgICAvLyB3aWxsIGJlIG9wdGltaXplZCBvdXQuCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4KICAgICAgICBzdHJ1Y3QgcmVtb3ZlX3N0cmluZzxULCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NjYWxhcjxUPjo6dmFsdWU+Ojp0eXBlPgogICAgICAgIHsKICAgICAgICAgICAgc3RhdGljIFQgY29udmVydChUIHZhbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIHZhbDsKICAgICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIC8vIEhhbmRsZXMgYmFzaWMgc3RyaW5ncyBieSByZXR1cm5pbmcgdGhlaXIgY19zdHIoKQogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIENoYXIsIHR5cGVuYW1lIFRyYWl0cz4KICAgICAgICBzdHJ1Y3QgcmVtb3ZlX3N0cmluZzxzdGQ6OmJhc2ljX3N0cmluZzxDaGFyLCBUcmFpdHM+LCB2b2lkPgogICAgICAgIHsKICAgICAgICAgICAgdHlwZWRlZiBzdGQ6OmJhc2ljX3N0cmluZzxDaGFyLCBUcmFpdHM+IHN0cmluZ190eXBlOwogICAgICAgICAgICBzdGF0aWMgYXV0byBjb252ZXJ0KGNvbnN0IHN0cmluZ190eXBlJiB2YWwpIC0+IGRlY2x0eXBlKHZhbC5jX3N0cigpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXR1cm4gdmFsLmNfc3RyKCk7CiAgICAgICAgICAgIH0KICAgICAgICB9OwoKICAgICAgICAvLyBEZWZhdWx0LCByZXNvcnQgdG8gc3RyaW5nc3RyZWFtIHRvIHJldHVybiBhIHN0cmluZyBmb3IgdGhlIHZhbHVlCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgRW5hYmxlID0gdm9pZD4KICAgICAgICBzdHJ1Y3QgcmVtb3ZlX29iamVjdAogICAgICAgIHsKICAgICAgICAgICAgc3RhdGljIHN0ZDo6c3RyaW5nIGNvbnZlcnQoY29uc3QgVCYgdmFsKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzdGQ6Om9zdHJpbmdzdHJlYW0gczsKICAgICAgICAgICAgICAgIHMgPDwgdmFsOwogICAgICAgICAgICAgICAgcmV0dXJuIHMuc3RyKCk7CiAgICAgICAgICAgIH0KICAgICAgICB9OwoKICAgICAgICAvLyBGb3IgcHJpbWF0aXZlcyArIHBvaW50ZXJzLCBqdXN0IGZvcndhcmQuICBOb3RlLCB0aGUgZGVjYXkgdXNlZCBlYXJsaWVyCiAgICAgICAgLy8gY2F1c2VzIGFycmF5cyB0byBkZWNheSB0byBwb2ludGVycyBhbmQgdXNlIHRoaXMuCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4KICAgICAgICBzdHJ1Y3QgcmVtb3ZlX29iamVjdDxULCB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzdGQ6OmlzX3NjYWxhcjxUPjo6dmFsdWU+Ojp0eXBlPgogICAgICAgIHsKICAgICAgICAgICAgc3RhdGljIFQgY29udmVydChUIHZhbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcmV0dXJuIHZhbDsKICAgICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIC8vIEZvciBzdGQ6OmJhc2ljX3N0cmluZywganVzdCBzaW1wbHkgZm9yd2FyZCB0aGUgcmVmZXJlbmNlLCBub3QgY29weSBpcyBuZWVkZWQKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBDaGFyLCB0eXBlbmFtZSBUcmFpdHM+CiAgICAgICAgc3RydWN0IHJlbW92ZV9vYmplY3Q8c3RkOjpiYXNpY19zdHJpbmc8Q2hhciwgVHJhaXRzPiwgdm9pZD4KICAgICAgICB7CiAgICAgICAgICAgIHR5cGVkZWYgc3RkOjpiYXNpY19zdHJpbmc8Q2hhciwgVHJhaXRzPiBzdHJpbmdfdHlwZTsKICAgICAgICAgICAgc3RhdGljIGNvbnN0IHN0cmluZ190eXBlJiBjb252ZXJ0KGNvbnN0IHN0cmluZ190eXBlJiB2YWwpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHJldHVybiB2YWw7CiAgICAgICAgICAgIH0KICAgICAgICB9OwoKICAgICAgICAvLyBGb3IgcmVmZXJlbmNlIHdyYXBwZXJzLCB1bndyYXAgdGhlIHJlZmVyZW5jZSwgYW5kIHRoZW4gZGVjYXkgaXQgYW5kIHJldHVybgogICAgICAgIC8vIHdoYXRldmVyIHRoYXQgd291bGQgcmV0dXJuLgogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+CiAgICAgICAgc3RydWN0IHJlbW92ZV9vYmplY3Q8c3RkOjpyZWZlcmVuY2Vfd3JhcHBlcjxUPiwgdm9pZCA+CiAgICAgICAgewogICAgICAgICAgICB0eXBlZGVmIHJlbW92ZV9vYmplY3Q8IHR5cGVuYW1lIHN0ZDo6ZGVjYXk8VD46OnR5cGUgPiBzdWJfY2FsbDsKICAgICAgICAgICAgc3RhdGljIGF1dG8gY29udmVydChzdGQ6OnJlZmVyZW5jZV93cmFwcGVyPFQ+IGNvbnN0JiByZWYpIC0+IGRlY2x0eXBlKHN1Yl9jYWxsOjpjb252ZXJ0KHJlZi5nZXQoKSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHJldHVybiBzdWJfY2FsbDo6Y29udmVydChyZWYuZ2V0KCkpOwogICAgICAgICAgICB9CiAgICAgICAgfTsKCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgLi4uIEFyZ3M+CiAgICAgICAgaW50IHByaW50Zihjb25zdCBjaGFyKiBmbXQsIGNvbnN0IEFyZ3MmLi4uIGFyZ3MpCiAgICAgICAgewogICAgICAgICAgICAvL3N0ZDo6Y291dCA8PCBfX1BSRVRUWV9GVU5DVElPTl9fIDw8IHN0ZDo6ZW5kbDsKICAgICAgICAgICAgcmV0dXJuIHN0ZDo6cHJpbnRmKGZtdCwgcmVtb3ZlX3N0cmluZzx0eXBlbmFtZSBzdGQ6OmRlY2F5PGNvbnN0IEFyZ3MmPjo6dHlwZSA+Ojpjb252ZXJ0KGFyZ3MpLi4uKTsKICAgICAgICB9CgogICAgfQoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIC4uLiBBcmdzPgogICAgaW50IHByaW50Zihjb25zdCBjaGFyKiBmbXQsIGNvbnN0IEFyZ3MmLi4uIGFyZ3MpCiAgICB7CiAgICAgICAgLy9zdGQ6OmNvdXQgPDwgX19QUkVUVFlfRlVOQ1RJT05fXyA8PCBzdGQ6OmVuZGw7CiAgICAgICAgcmV0dXJuIGRldGFpbDo6cHJpbnRmKGZtdCwgZGV0YWlsOjpyZW1vdmVfb2JqZWN0PHR5cGVuYW1lIHN0ZDo6ZGVjYXk8Y29uc3QgQXJncyY+Ojp0eXBlPjo6Y29udmVydChhcmdzKS4uLik7CiAgICB9CgogICAgdGVtcGxhdGU8dHlwZW5hbWUgLi4uIEFyZ3M+CiAgICBpbnQgcHJpbnRmKGNvbnN0IHN0ZDo6c3RyaW5nJiBmbXQsIGNvbnN0IEFyZ3MmLi4uIGFyZ3MpCiAgICB7CiAgICAgICAgcmV0dXJuIHByaW50ZihmbXQuY19zdHIoKSwgYXJncy4uLik7CiAgICB9Cgp9CgpzdHJ1Y3QgWAp7CiAgIGludCBpOwogICBleHBsaWNpdCBYKGludCBpKSA6CiAgIGkoaSkKICAgewogICB9Cn07CgpzdGQ6Om9zdHJlYW0mIG9wZXJhdG9yIDw8KHN0ZDo6b3N0cmVhbSYgc3RyLCBjb25zdCBYJiB4KQp7CiAgc3RyIDw8ICJYKCIgPDwgeC5pIDw8ICIpIjsKICByZXR1cm4gc3RyOwogIAp9CiAgCgogaW50IG1haW4oKQogewogICAgY29uc3Qgc3RkOjpzdHJpbmcgaCgiSGVsbG8iKTsKICAgIGNoYXIgd1tdID0gIldvcmxkIjsKICAgIGNvbnN0IGNoYXIqIHQgPSAiVGhlcmUhIjsKICAgIGNoYXIqIHcyID0gdzsKICAgIGludCBpID0gMTA7CiAgICBYIHgoNDU2KTsKICAgIHVzaW5nIHNhZmU6OnByaW50ZjsKCiAgICBwcmludGYoIiVzICVzICVzICVzICVkICVzLCAlcyAlZlxuIiwgaCwgdywgdCwgc3RkOjpzdHJpbmcoIlRlbXAiKSwgaSwgeCwgImZvbyIsIDAuMTIzNDUpOwoKICAgIHByaW50ZihzdGQ6OnN0cmluZygiJXMgJXMgJXNcbiIpLCAiTW9yZSBmdW4hIiwgeCwgdzIpOwoKICAgIHByaW50ZigiUmVmIFRlc3Q6ICVzICVzICVzXG4iLCBzdGQ6OnJlZih3KSwgc3RkOjpyZWYoaCksIHN0ZDo6Y3JlZih4KSk7ICAgIAp9