Skip to content

Instantly share code, notes, and snippets.

@kris7t
Last active August 29, 2015 14:07
Show Gist options
  • Save kris7t/82c6072d49eef18fa24f to your computer and use it in GitHub Desktop.
Save kris7t/82c6072d49eef18fa24f to your computer and use it in GitHub Desktop.
#include <iostream>
#include <ostream>
#include <type_traits>
#include <utility>
template <char X, char... Xs>
struct PrintfHelper {
template <std::size_t Ny, typename... Ys>
struct Inner {
static std::ostream &run(std::ostream &os, Ys &&... ys) {
return PrintfHelper<Xs...>::template Inner<Ny, Ys...>::run(
os << X, std::forward<Ys>(ys)...);
}
};
};
template <char... Xs>
struct PrintfHelper<'%', Xs...> {
template <std::size_t Ny, typename Y, typename... Ys>
struct Inner {
static std::ostream &run(std::ostream &os, Y &&y, Ys &&... ys) {
return PrintfHelper<Xs...>::template Inner<Ny - 1, Ys...>::run(
os << y, std::forward<Ys>(ys)...);
}
};
};
template <char... Xs>
struct PrintfHelper<'%', 'f', Xs...> {
template <std::size_t Ny, typename Y, typename... Ys>
struct Inner {
static std::ostream &run(std::ostream &os, double y, Ys &&... ys) {
return PrintfHelper<Xs...>::template Inner<Ny - 1, Ys...>::run(
os << y, std::forward<Ys>(ys)...);
}
};
};
template <char... Xs>
struct PrintfHelper<'%', '%', Xs...> {
template <std::size_t Ny, typename... Ys>
struct Inner {
static std::ostream &run(std::ostream &os, Ys &&... ys) {
return PrintfHelper<Xs...>::template Inner<Ny, Ys...>::run(
os << '%', std::forward<Ys>(ys)...);
}
};
};
template <>
struct PrintfHelper<'\0'> {
// Az Ys megeszi a hatralevo template argumentumokat, hogy lefusson a
// static_assert es ertelmes hibauzenetet kapjunk.
template <std::size_t Ny, typename... Ys>
struct Inner {
static_assert(Ny == 0, "Too many arguments");
static std::ostream &run(std::ostream &os) {
return os;
}
};
};
template <typename Char, Char... Xs>
struct Printf;
template <char... Xs>
struct Printf<char, Xs...> {
template <typename... Ys>
std::ostream &operator()(std::ostream &os, Ys &&... ys) const {
return PrintfHelper<Xs..., '\0'>::template Inner<sizeof...(Ys), Ys...>::run(os, std::forward<Ys>(ys)...);
}
};
template <typename Char, Char... Xs>
constexpr auto operator"" _printf() {
return Printf<Char, Xs...>{};
}
struct CastDemo {
double d;
constexpr explicit CastDemo(double x) : d{x} { }
operator double() const { return d; }
friend std::ostream &operator<<(std::ostream &os, CastDemo) {
return os << "CastDemo";
}
};
int main() {
CastDemo cd{3.14};
"%, %% % %\n"_printf(std::cout, 1, "foo", cd);
"%, %% % %f\n"_printf(std::cout, 1, "foo", cd);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment