Skip to content

Instantly share code, notes, and snippets.

@ldionne
Created March 12, 2015 01:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ldionne/a914d7f6605f17113040 to your computer and use it in GitHub Desktop.
Save ldionne/a914d7f6605f17113040 to your computer and use it in GitHub Desktop.
Create a printf-style format string at compile-time
#include <type_traits>
#include <boost/hana.hpp>
#include <boost/hana/ext/std/type_traits.hpp>
#include <iostream>
using namespace hana;
constexpr auto formats = hana::make_map(
hana::make<hana::Pair>(hana::type<int>, hana::string<'%', 'd'>),
hana::make<hana::Pair>(hana::type<float>, hana::string<'%', 'f'>),
hana::make<hana::Pair>(hana::type<char const*>, hana::string<'%', 's'>)
);
struct concat_strings {
template <char ...s1, char ...s2>
constexpr auto operator()(hana::_string<s1...>, hana::_string<s2...>) const
{ return hana::string<s1..., s2...>; }
};
template <typename ...Tokens>
constexpr auto format(Tokens ...tokens_) {
auto tokens = hana::make_tuple(tokens_...);
// If you don't care about constexpr-ness of `format`, you
// can use this lambda instead of `hana::demux(...)(...)`:
//
// [](auto token) {
// return hana::from_just(hana::lookup(formats,
// hana::decltype_(token)));
// }
auto format_string_tokens = hana::adjust(tokens,
hana::compose(hana::not_, hana::is_a<hana::String>),
hana::demux(hana::from_just)(
hana::compose(hana::partial(hana::lookup, formats),
hana::decltype_)
)
);
auto format_string = hana::foldl(
format_string_tokens, hana::string<>, concat_strings{}
);
auto variables = hana::filter(tokens,
hana::compose(hana::not_, hana::is_a<hana::String>)
);
return hana::prepend(format_string, variables);
}
template <char ...s>
char const string_literal[] = {s..., '\0'};
template <char ...s>
auto to_string_literal(hana::_string<s...> const&)
{ return string_literal<s...>; }
int main() {
int a = 1;
float b = 1.3;
char const* c = "abcdef";
auto args = format(
BOOST_HANA_STRING("first="), a
, BOOST_HANA_STRING(" second="), b
, BOOST_HANA_STRING(" third="), c
);
hana::unpack(args, [](auto fmt, auto ...args) {
return std::printf(to_string_literal(fmt), args...);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment