Skip to content

Instantly share code, notes, and snippets.

@lichray
Created February 13, 2016 11:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lichray/c7bc9744857abf26319d to your computer and use it in GitHub Desktop.
Save lichray/c7bc9744857abf26319d to your computer and use it in GitHub Desktop.
Produce type-generic character and string literals
#include <type_traits>
#include <utility>
namespace etude {
template<class... Fs>
struct overloaded_function_impl_;
template<>
struct overloaded_function_impl_<> {
template<class... Args,
typename std::enable_if<
sizeof...(Args) < 0 // always false
>::type* = nullptr
>
void operator()(Args...) const = delete;
};
template<class F, class = void>
struct function_holder_;
template<class F>
struct function_holder_<F,
typename std::enable_if<std::is_class<F>{}>::type>
: private F {
using F::operator();
template<class F_>
explicit function_holder_(F_ && f)
: F(std::forward<F_>(f)) {
}
};
template<class R, class... Args>
struct function_holder_<R (*)(Args...)> {
explicit function_holder_(R (*f)(Args...))
: f_(f) {
}
// should not be template
R operator()(Args... args) const {
return (*f_)(std::forward<Args>(args)...);
}
private:
R (*f_)(Args...);
};
template<class F, class... Fs>
struct overloaded_function_impl_<F, Fs...>
: private function_holder_<F>,
private overloaded_function_impl_<Fs...> {
typedef function_holder_<F> base1;
typedef overloaded_function_impl_<Fs...> base2;
using base1::operator();
using base2::operator();
template<class F_, class... Fs_>
overloaded_function_impl_(F_ && f, Fs_&&... fs)
: base1(std::forward<F_>(f)), base2(std::forward<Fs_>(fs)...) {
}
};
template<class... Fs>
class overloaded_function {
typedef overloaded_function_impl_<Fs...> impl_t;
public:
template<class... Fs_,
typename std::enable_if<
sizeof...(Fs) == sizeof...(Fs_)
>::type* = nullptr
>
overloaded_function(Fs_&&... fs)
: impl_(std::forward<Fs_>(fs)...) {
}
template<class... Args>
auto operator()(Args&&... args)
-> decltype(std::declval<impl_t&>()(std::forward<Args>(args)...)) {
return impl_(std::forward<Args>(args)...);
}
template<class... Args>
auto operator()(Args&&... args) const
-> decltype(std::declval<impl_t const&>()(std::forward<Args>(args)...)) {
return impl_(std::forward<Args>(args)...);
}
private:
overloaded_function_impl_<Fs...> impl_;
};
template<class... Fs>
auto make_overloaded(Fs... fs)
-> overloaded_function<Fs...> {
return {std::forward<Fs>(fs)...};
}
} // namespace etude
#define G_literal(t, literal) \
etude::make_overloaded( \
[](char) -> decltype(auto) { return literal; }, \
[](wchar_t) -> decltype(auto) { return L ## literal; }, \
[](char16_t) -> decltype(auto) { return u ## literal; }, \
[](char32_t) -> decltype(auto) { return U ## literal; })(t{})
#include <iostream>
int main()
{
std::wcout << G_literal(wchar_t, 'a') << std::endl;
std::wcout << G_literal(wchar_t, "meow") << std::endl;
std::wcout << G_literal(char, "stl") << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment