Created
March 12, 2015 01:00
-
-
Save ldionne/a914d7f6605f17113040 to your computer and use it in GitHub Desktop.
Create a printf-style format string 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 <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