Created
February 13, 2016 11:30
-
-
Save lichray/c7bc9744857abf26319d to your computer and use it in GitHub Desktop.
Produce type-generic character and string literals
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 <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