is there a std::optional_function like the given - c++

I am searching for something like swifts ? operator in c++ for std::function. I have grown to like it over the last couple years.
I would like a std::optional_function, which only calls the function if the function exists.
Something like this (but written by the gods of c++):
template<typename R>
struct option_function_result {
bool executed;
R result;
} ;
template<>
struct option_function_result<void>
{
bool executed;
} ;
template<typename F>
class optional_function
{
public:
typedef std::function<F> function_type;
typedef option_function_result<typename function_type::result_type> result_type;
protected:
function_type f;
public:
template<typename Fn>
optional_function operator=(const Fn &f_)
{
f = f_;
return *this;
}
template<typename Fn>
optional_function operator=(Fn &&f_)
{
f = std::forward<Fn>(f_);
return *this;
}
operator bool() const
{
return (bool)f;
}
template<typename ...Args, typename R>
result_type operator()(Args... args)
{
if (f)
return result_type { true, f(args...) };
return result_type { false };
}
template<typename ...Args>
result_type operator()(Args... args)
{
if (f)
{
f(args...);
return result_type { true };
}
return result_type { false };
}
} ;
Another revision
Here is revision 2. In order not to polute the question, and since I don't know if this will be a final answer, I'm gonna place it here for now:
I expect that the constructor for the struct is not necessary. However it forces the compiler to give me errors I need to debug the compilation.
template<typename R>
struct optional_function_result {
bool executed;
R result;
optional_function_result(bool &&executed_, R &&result_) :
executed (executed_),
result(result_) {}
} ;
template<>
struct optional_function_result<void>
{
bool executed;
optional_function_result(bool &&executed_) :
executed (executed_) {}
} ;
template<typename F>
class optional_function
{
public:
typedef std::function<F> function_type;
typedef typename std::function<F>::result_type function_result_type;
typedef optional_function_result<typename function_type::result_type> result_type;
protected:
function_type f;
public:
template<typename Fn>
optional_function operator=(const Fn &f_)
{
f = f_;
return *this;
}
template<typename Fn>
optional_function operator=(Fn &&f_)
{
f = std::forward<Fn>(f_);
return *this;
}
operator bool() const
{
return (bool)f;
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<!std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
return {
true,
std::forward<typename function_type::result_type>(f(args...))
};
return {
false,
function_result_type()
};
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
{
f(args...);
return { true };
}
return { false };
}
} ;
Ok one more version, which uses basically optional to get rid of some edge cases.
template<typename T>
using optional_type = std::experimental::optional<T>;
template<typename R>
struct optional_function_result : optional_type<R> {
typedef optional_type<R> super_type;
optional_function_result() :
super_type() {}
optional_function_result(R &&result_) :
super_type(result_) {}
bool executed() const { return this->has_result(); }
} ;
template<>
struct optional_function_result<void>
{
bool executed_;
optional_function_result(bool &&executed__) :
executed_ (executed__) {}
bool executed() const { return executed_; }
} ;
template<typename F>
class optional_function
{
public:
typedef std::function<F> function_type;
typedef typename std::function<F>::result_type function_result_type;
typedef optional_function_result<typename function_type::result_type> result_type;
protected:
function_type f;
public:
template<typename Fn>
optional_function operator=(const Fn &f_)
{
f = f_;
return *this;
}
template<typename Fn>
optional_function operator=(Fn &&f_)
{
f = std::forward<Fn>(f_);
return *this;
}
operator bool() const
{
return (bool)f;
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<!std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
return {
std::forward<typename function_type::result_type>(f(args...))
};
return {};
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
{
f(args...);
return { true };
}
return { false };
}
} ;

The ? operator works really well in C++ too:
// let function be of type std::function or a function pointer
auto var = f ? f() : default_value;
If you really want a type that does that, there is no such thing in the standard library, but a simple function is enough to do what you want (works only for function that don't return references or void):
template<typename F, typename... Args, typename R = std::invoke_result_t<F, Args&&...>>
auto optionally_call(F&& f, Args&&... args) -> std::optional<R> {
return f ? R(std::forward<F>(f)(std::forward<Args>(args)...)) : std::nullopt;
}
With some metaprogramming, it's possible to support cases not supported by this implementation.
This is to highlight that there's a lot of pitfalls when creating a whole type that is meant to be generic. There are many mistakes and performance issues and even code that will cannot be called in your sample code. A simple utility function would be easier than a type.

The standard library doesn't have anything like that, but you can build one yourself:
#include <functional>
#include <iostream>
#include <optional>
template <typename T>
class optional_function {
private:
std::optional<T> func;
public:
optional_function(T f) : func{std::move(f)} {}
optional_function() = default;
template <typename... Args>
auto operator()(Args&&... args) const {
using func_invoke_type = decltype((*func)(std::forward<Args>(args)...));
constexpr bool func_invoke_type_is_void = std::is_same_v<void, func_invoke_type>;
using optional_result_type = std::optional<
std::conditional_t<
func_invoke_type_is_void, // Can't have a std::optional<void>
char,
std::conditional_t<
std::is_reference_v<func_invoke_type>, // Can't have a std::optional<T&>
std::reference_wrapper<std::remove_reference_t<func_invoke_type>>,
func_invoke_type
>
>
>;
if (func) {
if constexpr (!func_invoke_type_is_void) {
return optional_result_type{(*func)(std::forward<Args>(args)...)};
} else {
(*func)(std::forward<Args>(args)...);
return optional_result_type{ '\0' }; // can't return void{} '
}
}
return optional_result_type{};
}
};
// Test it
void foo() {}
int main() {
optional_function f1{[](int i) { return i * i; }};
optional_function f2{[] { std::cout << "Hello World\n"; }};
decltype(f1) f3{};
optional_function f4{[](int a, const int& b) -> int const& {
std::cout << a + b << '\n';
return b;
}};
optional_function f5{foo};
auto res1 = f1(9);
auto res2 = f2();
auto res3 = f3(9);
int b = 5;
auto res4 = f4(1, b);
auto res5 = f5();
std::cout << std::boolalpha;
std::cout << "f1 is executed: " << res1.has_value() << ". result: " << *res1
<< '\n';
std::cout << "f2 is executed: " << res2.has_value() << '\n';
std::cout << "f3 is executed: " << res3.has_value() << '\n';
std::cout << "f4 is executed: " << res4.has_value() << ". result: " << *res4
<< '\n';
std::cout << "f5 is executed: " << res5.has_value() << '\n';
}

No, there is currently no such thing in the C++ Standard Library.

Related

C++ introspection on identifying existence of method signatures

I'd like to modernise a common technique I use or perhaps over use. It statically checks for method signatures and calls the methods if they exist. My approach predates C++17 by some time FWIW.
Currently, I used Boost's Type traits like BOOST_TTI_HAS_MEMBER_FUNCTION(event)
which allows something such as
template <typename M, typename E>
static inline typename std::enable_if<
has_member_function_event<current_t, void, boost::mpl::vector<M &, const E &>>::value
>::type
event(M &mux, S &g, const E &e) {
auto &node = boost::fusion::at<N>(g);
node.event(mux, e);
...
It works just fine but, you know, it's not the prettiest. Is there a way I might avoid the macros and join the rest of you in the modern world :-)?
Regards,
--Matt. (aka dinosaur)
Would simple, direct SFINAE suit your needs?
Here's a test function exercising various member functions, checking for adequate return types and const-correctness as well:
template <typename Obj> void exercise(Obj&& obj) {
if constexpr(has_bar(obj)) {
std::cout << "called T bar() -> something or void\n";
obj.bar();
}
if constexpr(converts<int>(has_foo(obj))) {
std::cout << "called int foo() const -> " << obj.foo() << "\n";
}
if constexpr(converts<long>(has_foo(obj, "some text"))) {
std::cout << "called long foo(std::string) -> " << obj.foo("some text") << "\n";
}
}
The has_bar implementation is simply:
template <typename T>
static constexpr auto has_bar(T&& obj) -> exists<decltype(obj.bar())> { return {}; }
template <typename... T>
static constexpr auto has_bar(T&&...) -> does_not_exist { return {}; }
To generically allow for checking signatures and avoid repetitious code, here's a helper macro (obviously optional):
#define DEF_HAS_MEMBER(name) \
template <typename T, typename... Args> \
static constexpr auto has_##name(T&& obj, Args&&... args) \
-> exists<decltype(std::forward<T>(obj).name(std::forward<Args>(args)...))> { return {}; } \
template <typename... T> \
static constexpr auto has_##name(T&&...) -> does_not_exist { return {}; }
DEF_HAS_MEMBER(foo)
DEF_HAS_MEMBER(bar)
The converts predicate now is an ultra-simple addition:
template <typename T, typename R>
static constexpr auto converts(R) { return std::is_convertible_v<typename R::return_type, T>; }
Everything together:
Live On Coliru
#include <string>
#include <type_traits>
#include <iostream>
template <typename R> struct exists : std::true_type { using return_type = R; };
struct does_not_exist : std::false_type { using return_type = void; };
#define DEF_HAS_MEMBER(name) \
template <typename T, typename... Args> \
static constexpr auto has_##name(T&& obj, Args&&... args) \
-> exists<decltype(std::forward<T>(obj).name(std::forward<Args>(args)...))> { return {}; } \
template <typename... T> \
static constexpr auto has_##name(T&&...) -> does_not_exist { return {}; }
DEF_HAS_MEMBER(foo)
DEF_HAS_MEMBER(bar)
struct Everything {
int foo(std::string /*unused*/) { return 42; }
int foo() const { return -1; }
void bar() {}
};
struct Some {
int foo() const { return -2; }
};
template <typename T, typename R>
static constexpr auto converts(R) { return std::is_convertible_v<typename R::return_type, T>; }
template <typename Obj> void exercise(Obj&& obj) {
std::cout << "===== " << __PRETTY_FUNCTION__ << "\n";
if constexpr(has_bar(obj)) {
std::cout << "called T bar() -> something or void\n";
obj.bar();
}
if constexpr(converts<int>(has_foo(obj))) {
std::cout << "called int foo() const -> " << obj.foo() << "\n";
}
if constexpr(converts<long>(has_foo(obj, "some text"))) {
std::cout << "called long foo(std::string) -> " << obj.foo("some text") << "\n";
}
}
int main() {
Everything e;
Everything const ce;
Some s;
Some const cs;
exercise(s);
exercise(cs);
exercise(ce);
exercise(e);
}
Prints
===== void exercise(Obj&&) [with Obj = Some&]
called int foo() const -> -2
===== void exercise(Obj&&) [with Obj = const Some&]
called int foo() const -> -2
===== void exercise(Obj&&) [with Obj = const Everything&]
called int foo() const -> -1
===== void exercise(Obj&&) [with Obj = Everything&]
called T bar() -> something or void
called int foo() const -> -1
called long foo(std::string) -> 42
OK. I have taken Alan Birtles advice and had a look at C++20 concepts for the solution.
Perhaps the use of std::addressof is overkill but it makes it almost a one-liner without a macro to define a HasMethodXYZ concept which may then be used for if constexpr or for easy SFINAE via a constraint. For example:
template <typename T>
concept HasMethodEvent = requires(T a, void (T::*m)(const std::string&) const) {
{&a == std::addressof(a)};
{m = &T::event};
};
struct dude_noway {};
struct dude_no {
void event(std::string& f) const {}
};
struct dude_yes {
void event(const std::string& f) const {}
};
template <typename T>
bool perhaps_event() {
if constexpr (HasMethodEvent<T>) {
return true;
} else {
return false;
}
}
template <HasMethodEvent T>
bool perhaps_event_sfinae() {
return true;
}
template <typename T>
bool perhaps_event_sfinae() {
return false;
}
//Catch2 test-case check
TEST_CASE("simple event check", "[check_method]") {
REQUIRE(perhaps_event<dude_yes>());
REQUIRE_FALSE(perhaps_event<dude_no>());
REQUIRE_FALSE(perhaps_event<dude_noway>());
REQUIRE(perhaps_event_sfinae<dude_yes>());
REQUIRE_FALSE(perhaps_event_sfinae<dude_no>());
REQUIRE_FALSE(perhaps_event_sfinae<dude_noway>());
}
which works OK with clang++-10 using libstdc++-10. For the win, I prefer this to the Boost TTI approach as it co-locates the method signature with the method name as part of the concept rather than using the MPL vector later and it feels simpler.
Thanks, --Matt.

How can I write a function that both input and output is a std::variant

I want to write a function that both input and output are variants.
VariantTypeA GetA(const VariantTypeB& b) {
return std::visit(MyVisitor(), b);
}
But I got a exception saying that
std::visit` requires the visitor to have a single return type.
How can I write a function like that? Can I use switch instead? How?
Use a visitor with return type VariantTypeA.
Using std::variant and letting the visitor deduce the element doesn't work if the variant has duplicate alternative types. Here's a function template variant_visit that preserves the index() of the variant. variant_visit also sets the corresponding alternative type in the result variant to std::monostate if the visitor returns void for some argument, because std::variant with void is ill-formed. SFINAE is omitted for simplicity.
namespace detail {
template <typename T>
using wrap_void_t = std::conditional_t<std::is_void_v<T>, std::monostate, T>;
template <typename Variant, typename Func,
typename = std::make_index_sequence<std::variant_size_v<
std::remove_reference_t<Variant>
>>>
struct result_variant;
template <typename Variant, typename Func, std::size_t... Is>
struct result_variant<Variant, Func, std::index_sequence<Is...>> {
using type = std::variant<
wrap_void_t<
std::invoke_result_t<
Func,
decltype(std::get<Is>(std::declval<Variant>()))
>
> ...
>;
};
template <typename Variant, typename Func>
using result_variant_t = typename result_variant<Variant, Func>::type;
template <typename Variant, typename Visitor, std::size_t... Is>
auto variant_visit(Variant&& variant, Visitor&& visitor, std::index_sequence<Is...>)
{
using Ret = result_variant_t<Variant, Visitor>;
using fp_t = Ret (*)(Variant&&, Visitor&&);
const fp_t fp_array[] = {
[](Variant&&, Visitor&&) -> Ret { throw std::bad_variant_access{}; },
[](Variant&& variant, Visitor&& visitor) -> Ret {
if constexpr (std::is_same_v<std::variant_alternative_t<Is, Ret>,
std::monostate>) {
std::invoke(std::forward<Visitor>(visitor),
std::get<Is>(std::forward<Variant>(variant)));
return Ret(std::in_place_index<Is>);
} else {
return Ret(
std::in_place_index<Is>,
std::invoke(std::forward<Visitor>(visitor),
std::get<Is>(std::forward<Variant>(variant)))
);
}
} ...
};
auto fp = fp_array[static_cast<std::size_t>(variant.index() + 1)];
return fp(std::forward<Variant>(variant), std::forward<Visitor>(visitor));
}
}
template <typename Variant, typename Visitor>
auto variant_visit(Variant&& variant, Visitor&& visitor)
{
return detail::variant_visit(
std::forward<Variant>(variant),
std::forward<Visitor>(visitor),
std::make_index_sequence<
std::variant_size_v<std::remove_reference_t<Variant>>
>{}
);
}
Usage example:
int main()
{
{
std::variant<int, int, double> var{std::in_place_index<1>, 10};
auto result = variant_visit(var, std::negate{});
std::cout << std::get<1>(result) << '\n';
}
{
std::variant<int, int, double> var{std::in_place_index<2>, 2e20};
auto result = variant_visit(var, std::negate{});
std::cout << std::get<2>(result) << '\n';
}
{
std::variant<std::unique_ptr<int>> var{std::make_unique<int>(30)};
auto result = variant_visit(var, [](auto& ptr) { return -*ptr; });
std::cout << std::get<0>(result) << '\n';
}
{
auto inspector = [](auto&& ptr) {
if constexpr (std::is_const_v<std::remove_reference_t<decltype(ptr)>>) {
std::cout << "const";
}
if constexpr (std::is_lvalue_reference_v<decltype(ptr)>) {
std::cout << "&\n";
} else {
std::cout << "&&\n";
}
};
std::variant<std::unique_ptr<int>> var{std::make_unique<int>(30)};
variant_visit(var, inspector);
variant_visit(std::as_const(var), inspector);
variant_visit(std::move(var), inspector);
}
}
Output:
-10
-2e+20
-30
&
const&
&&
(live demo)
You can do it by simply wrapping the visitor in a lambda that performs the conversion back to a variant:
template <class Visitor, class Variant>
auto variant_visit(Visitor &&visitor, Variant &&variant) {
return std::visit(
[&](auto &&in) -> std::remove_reference_t<Variant> {
return visitor(static_cast<decltype(in)>(in));
},
std::forward<Variant>(variant)
);
}
See it live on Wandbox

How to handle an api which returns different data types for the same input data types?

How to handle an api which returns different data types for the same input data types?
Looking at the below example, apicall should return a date or a string depending on the input attribute:
#include <iostream>
#include <string>
using namespace std;
???? apicall(string datatype, string attribute)
{
// code
}
int main(int argc, char** argv)
{
string datatype = "Thomas"
string attribute = "bithday"
cout << apicall(datatype, attribute) << endl;
string datatype = "Thomas"
string attribute = "address"
cout << apicall(datatype, attribute) << endl;
}
What could be in place of ???? (apicall return datatype) and how to handle these cases?
I am trying to understand these concepts as my experience to date has been with duck typed scripting languages.
The ideal solution is to use a std::variant, which is a safe union type like.
This allows you to write the following:
using DateOrString = std::variant<DateType, std::string>;
DateOrString api_call(std::string, std::string) {
// you can return both DateType and std::string
}
// ...
auto result = api_call("", "");
auto& str = std::get<std::string>(result);
Unfortunately std::variant is a C++17 feature. However different compilers already support it.
As already has been suggested, boost has a variant class and you can use it with any C++ standard.
As last option, you may implement a "variant-like" class which handles both a date and a string. Your function should return it.
Here a demo how to quickly implement that kind of class.
Note that that class is safe because the type is checked at runtime.
As a variant object, your callee function should branch on the type, something like:
auto result = api_call(/*...*/);
if (result.is_string()) {
// result is a string
const auto& str = result.get_string();
} else {
// result is a date
const auto& date = result.get_date();
}
... returns different data types for the same input data types?
This is literally impossible. A function is defined with one (or zero) return types, and zero or more input parameter types.
The workarounds are:
Write a single function returning a variant type, such as std::variant in C++17, or Boost.Variant if that's not available.
Write multiple functions with different return types (the caller just has to choose the right one)
Invert control, so that instead of returning a value, you pass an object capable of processing all the required types:
struct APIHandler {
virtual ~APIHandler() {}
virtual void operator()(int) {}
virtual void operator()(string) {}
};
void apicall(string name, string attr, APIHandler &h) {
// dummy implementation
if (attr == "address") {
h("123 Woodford Road");
} else if (attr == "birthday") {
h(19830214);
}
}
// implement your type-specific logic here
struct MyHandler: APIHandler {
void operator()(int i) override {
cout << "got an int:" << i << '\n';
}
void operator()(string s) override {
cout << "got a string:" << s << '\n';
}
};
// and use it like:
MyHandler mh;
apicall("Thomas", "birthday", mh);
apicall("Thomas", "address", mh);
You want a std::variant in C++17 or a boost::variant or roll your own crude variant something like this:
constexpr std::size_t max() { return 0; }
template<class...Ts>
constexpr std::size_t max( std::size_t t0, Ts...ts ) {
return (t0<max(ts...))?max(ts...):t0;
}
template<class T0, class...Ts>
struct index_of_in;
template<class T0, class...Ts>
struct index_of_in<T0, T0, Ts...>:std::integral_constant<std::size_t, 0> {};
template<class T0, class T1, class...Ts>
struct index_of_in<T0, T1, Ts...>:
std::integral_constant<std::size_t,
index_of_in<T0, Ts...>::value+1
>
{};
struct variant_vtable {
void(*dtor)(void*) = 0;
void(*copy)(void*, void const*) = 0;
void(*move)(void*, void*) = 0;
};
template<class T>
void populate_vtable( variant_vtable* vtable ) {
vtable->dtor = [](void* ptr){ static_cast<T*>(ptr)->~T(); };
vtable->copy = [](void* dest, void const* src){
::new(dest) T(*static_cast<T const*>(src));
};
vtable->move = [](void* dest, void* src){
::new(dest) T(std::move(*static_cast<T*>(src)));
};
}
template<class T>
variant_vtable make_vtable() {
variant_vtable r;
populate_vtable<T>(&r);
return r;
}
template<class T>
variant_vtable const* get_vtable() {
static const variant_vtable table = make_vtable<T>();
return &table;
}
template<class T0, class...Ts>
struct my_variant {
std::size_t index = -1;
variant_vtable const* vtable = 0;
static constexpr auto data_size = max(sizeof(T0),sizeof(Ts)...);
static constexpr auto data_align = max(alignof(T0),alignof(Ts)...);
template<class T>
static constexpr std::size_t index_of() {
return index_of_in<T, T0, Ts...>::value;
}
typename std::aligned_storage< data_size, data_align >::type data;
template<class T>
T* get() {
if (index_of<T>() == index)
return static_cast<T*>((void*)&data);
else
return nullptr;
}
template<class T>
T const* get() const {
return const_cast<my_variant*>(this)->get<T>();
}
template<class F, class R>
using applicator = R(*)(F&&, my_variant*);
template<class T, class F, class R>
static applicator<F, R> get_applicator() {
return [](F&& f, my_variant* ptr)->R {
return std::forward<F>(f)( *ptr->get<T>() );
};
}
template<class F, class R=typename std::result_of<F(T0&)>::type>
R visit( F&& f ) & {
if (index == (std::size_t)-1) throw std::invalid_argument("variant");
static const applicator<F, R> table[] = {
get_applicator<T0, F, R>(),
get_applicator<Ts, F, R>()...
};
return table[index]( std::forward<F>(f), this );
}
template<class F,
class R=typename std::result_of<F(T0 const&)>::type
>
R visit( F&& f ) const& {
return const_cast<my_variant*>(this)->visit(
[&f](auto const& v)->R
{
return std::forward<F>(f)(v);
}
);
}
template<class F,
class R=typename std::result_of<F(T0&&)>::type
>
R visit( F&& f ) && {
return visit( [&f](auto& v)->R {
return std::forward<F>(f)(std::move(v));
} );
}
explicit operator bool() const { return vtable; }
template<class T, class...Args>
void emplace( Args&&...args ) {
clear();
::new( (void*)&data ) T(std::forward<Args>(args)...);
index = index_of<T>();
vtable = get_vtable<T>();
}
void clear() {
if (!vtable) return;
vtable->dtor( &data );
index = -1;
vtable = nullptr;
}
~my_variant() { clear(); }
my_variant() {}
void copy_from( my_variant const& o ) {
if (this == &o) return;
clear();
if (!o.vtable) return;
o.vtable->copy( &data, &o.data );
vtable = o.vtable;
index = o.index;
}
void move_from( my_variant&& o ) {
if (this == &o) return;
clear();
if (!o.vtable) return;
o.vtable->move( &data, &o.data );
vtable = o.vtable;
index = o.index;
}
my_variant( my_variant const& o ) {
copy_from(o);
}
my_variant( my_variant && o ) {
move_from(std::move(o));
}
my_variant& operator=(my_variant const& o) {
copy_from(o);
return *this;
}
my_variant& operator=(my_variant&& o) {
move_from(std::move(o));
return *this;
}
template<class T,
typename std::enable_if<!std::is_same<typename std::decay<T>::type, my_variant>{}, int>::type =0
>
my_variant( T&& t ) {
emplace<typename std::decay<T>::type>(std::forward<T>(t));
}
};
then your code looks like:
variant<string, int> apicall(string datatype, string attribute)
{
if (datatype > attribute) return string("hello world");
return 7;
}
int main()
{
string datatype = "Thomas"
string attribute = "bithday"
apicall(datatype, attribute).visit([](auto&&r){
cout << r << endl;
});
string datatype = "Thomas"
string attribute = "address"
apicall(datatype, attribute).visit([](auto&& r){
cout << r << endl;
});
}
with whatever visit or apply_visitor free function or method your particular variant supports.
This gets much more annoying in C++11 as we don't have generic lambdas.
You could use a variant, but it's up to the caller site to check the results. Boost and std defines two variant types, i.e. std::variant and std::any.

Wrapping a templated function call in a lambda

I am trying to write code to do something similar (code written for demonstration purposes) to this:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo([func](Args... args) -> std::result_of<F>::type
{
// Do something before calling func
func(args...);
// Do something after call func
});
}
So basically I am trying to write a function that returns an object that takes lambda that matches the templated function type. Obviously this code won't work because I do not have Args... defined. How would I solve this in C++11?
template<class F_before, class F, class F_after>
struct decorate_func_t {
F_before f0;
F f1;
F_after f2;
template<class...Args>
typename std::result_of<F(Args...)>::type operator()(Args&&...args)const{
f0();
auto r = f1(std::forward<Args>(args)...);
f2();
return r;
}
};
template<class F_before, class F, class F_after>
decorate_func_t<F_before, F, F_after>
decorate_func( F_before before, F f, F_after after ){
return {std::move(before), std::move(f), std::move(after)};
}
Then:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo(decorate_func(
[]{/* Do something before calling func */},
func,
[]{/* Do something after call func */ }
};
}
the lack of auto parameters in C++11 lambdas makes this about the best you can do.
In C++14 this is trivial:
template <class F>
auto runFunc(F func)
{
return foo(
[func](auto&&... args) // ->decltype(auto) maybe
{
// Do something before calling func
auto r = func(decltype(args)(args)...);
// Do something after call func
return r;
}
);
}
note that many nominally C++11 compilers actually support auto parameters on lambdas.
You can use a support structure as in the following example:
#include<type_traits>
#include<cassert>
struct foo {
template<typename F>
foo(F f) { assert(42 == f(42)); }
};
template<typename>
struct S;
template<typename R, typename... Args>
struct S<R(*)(Args...)> {
template <typename F>
static auto runFunc(F func) -> foo
{
return foo{[func](Args... args) -> R
{
// Do something before calling func
auto r = func(args...);
// Do something after call func
return r;
}};
}
};
template<typename F>
inline auto runFunc(F func) -> foo
{
return S<F>::runFunc(func);
}
int f(int i) { return i; }
int main() {
runFunc(f);
}
For it's not clear to me what's the context of the problem, I'm not sure I got exactly what you were asking for.
I hope the code above can help you.
Still being unsure it this is what you're searching for, I risk posting:
#include <iostream>
struct foo
{
template<typename T>
foo(T lambda)
{
lambda(1, 2);
}
};
template <typename F, typename... Args>
inline typename std::result_of<F>::type runFunc(F func)
{
return foo(
[func](Args... args)
{
std::cout << "Before";
func(args...);
std::cout << "After";
}
);
}
struct print
{
void operator()(int i) const
{
std::cout << i << std::endl;
}
void operator()(int i, int j) const
{
std::cout << i << " " << j << std::endl;
}
};
int main()
{
runFunc<print, int, int>(print());
}

boost::typeindex::type_id<T>().pretty_name() is not "pretty"

I am trying to have the type of some variable printed on stdout. This code:
std::string mystr {"dsadsadas"};
std::cout << boost::typeindex::type_id< decltype(mystr) >().pretty_name() << std::endl;
results in:
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1:: allocator<char> >
which is definitely not pretty.. why is this happening? any workaround?? (Note I'm compiling with clang++ using c++14 semantics)
I have a library called cpputil (privately maintained on bitbucket) which has lots of useful shortcuts for c++11 or better.
one of the concepts is cpputil::classname_of(x).
The idea is that if a class has a static member data or function called classname, this is used to print the name of the class. If not, you can supply a free function that provides the classname. Failing that, typeid.name() is used as a fallback.
Now your classnames can be as pretty as you like.
Live On Coliru
#include <iostream>
#include <type_traits>
/// static member of any type
namespace cpputil {
namespace detail {
template<class T>
constexpr auto has_static_member_classname(...)
-> std::false_type
{
return {};
}
template<class T>
constexpr auto has_static_member_classname(int)
-> decltype(T::classname, void(), std::true_type())
{
return {};
}
// static member of type function that returns anything but takes no args
template<class T>
constexpr auto has_static_function_classname(...)
-> std::false_type
{ return {}; }
template<class T>
constexpr auto has_static_function_classname(int)
-> decltype(T::classname(), void(), std::true_type())
{ return {}; }
}
// templated free function that takes no args, used as a fallback but may be overriden
template<class T> decltype(auto) classname() { return typeid(T).name(); }
namespace detail {
template<class T>
constexpr auto has_free_function_classname_0(...)
-> std::false_type
{ return {}; }
template<class T>
constexpr auto has_free_function_classname_0(int)
-> decltype(classname<T>(), void(), std::true_type())
{ return {}; }
// free function that takes a const ref
template<class T>
constexpr auto has_free_function_classname_1(...)
-> std::false_type
{ return {}; }
template<class T>
constexpr auto has_free_function_classname_1(int)
-> decltype(classname(std::declval<T>()), void(), std::true_type())
{ return {}; }
template<class T, typename = void>
struct classname_finder;
// highest priority - if there is a free function taking 1 parameter findable by ADL - use this
template<class T>
struct classname_finder<
T,
std::enable_if_t<
decltype(has_free_function_classname_1<T>(0))::value
>
>
{
static constexpr decltype(auto) apply() { return classname(*reinterpret_cast<const T*>(0)); }
static constexpr decltype(auto) apply(const T& t) { return classname(t); }
};
// priority 2 - if there is a static function, use that
template<class T>
struct classname_finder<
T,
std::enable_if_t<
decltype(has_static_function_classname<T>(0))::value &&
!decltype(has_free_function_classname_1<T>(0))::value
>
>
{
static constexpr decltype(auto) apply() { return T::classname(); }
static constexpr decltype(auto) apply(const T&) { return T::classname(); }
};
// priority 3 - if there is a static data member, use that
template<class T>
struct classname_finder<
T,
std::enable_if_t<
decltype(has_static_member_classname<T>(0))::value &&
!decltype(has_static_function_classname<T>(0))::value &&
!decltype(has_free_function_classname_1<T>(0))::value
>
>
{
static constexpr decltype(auto) apply() { return T::classname; }
static constexpr decltype(auto) apply(const T&) { return T::classname; }
};
// finally, use the cpputil::classname_of<X>() template overload
template<class T>
struct classname_finder<
T,
std::enable_if_t<
!decltype(has_static_member_classname<T>(0))::value &&
!decltype(has_static_function_classname<T>(0))::value &&
!decltype(has_free_function_classname_1<T>(0))::value &&
decltype(has_free_function_classname_0<T>(0))::value
>
>
{
static constexpr decltype(auto) apply() { return classname<T>(); }
static constexpr decltype(auto) apply(const T&) { return classname<T>(); }
};
}
template<class T>
auto classname_of(const T& t)
{
return detail::classname_finder<T>::apply(t);
}
template<class T>
auto classname_of()
{
return detail::classname_finder<T>::apply();
}
}
struct class_a
{
static const char* classname() { return "class_a"; }
};
struct class_b
{
constexpr static const char* classname = "class_b";
};
struct class_c
{
};
namespace cpputil {
template<> decltype(auto) classname<class_c>() { return "class_c"; }
}
struct class_d
{
};
decltype(auto) classname(const class_d&) { return "class_d"; }
struct class_e {
static const std::string& classname() { static const std::string _("class_e static function"); return _; }
};
static const char* classname(const class_e&) {
return "class_e free function should take priority";
}
// no classname decoration. should fall back to typeid() solution
struct class_f {
};
using namespace std;
auto main() -> int
{
class_a a;
class_b b;
class_c c;
class_d d;
class_e e;
class_f f;
cout << cpputil::classname_of(a) << endl;
cout << cpputil::classname_of(b) << endl;
cout << cpputil::classname_of(c) << endl;
cout << cpputil::classname_of(d) << endl;
cout << cpputil::classname_of(e) << endl;
cout << cpputil::classname_of(f) << endl;
cout << endl;
cout << cpputil::classname_of<class_a>() << endl;
cout << cpputil::classname_of<class_b>() << endl;
cout << cpputil::classname_of<class_c>() << endl;
cout << cpputil::classname_of<class_d>() << endl;
cout << cpputil::classname_of<class_e>() << endl;
cout << cpputil::classname_of<class_f>() << endl;
return 0;
}
Prints
class_a
class_b
class_c
class_d
class_e free function should take priority
7class_f
class_a
class_b
class_c
class_d
class_e free function should take priority
7class_f