Call fallback method if method does not exist - c++

I want to be able to do the following in C++
Try to call a function from a namespace, e.g., boost::filesystem::copy
If copy is not a member of boost::filesystem, call a fallback function, e.g., boost::filesystem3::copy
If fallback function does not exist (this could be either because boost does not have member filesystem3, or because boost::filesystem3 does not have member copy), the code should not compile.
After reading loads and loads of extremely long and complicated pieces of code, it is unclear to me what the simple way of doing this would be. A C++11 solution is fine. But the code sometimes requires to compile with an old boost version (1.39.0), which is precisely why this workaround is required.
Currently I do it by creating method alias after checking the BOOST_VERSION macro. But it would be good to know of a more sophisticated alternative that could be applicable for more general cases.

Here is a possible solution with which you can do that.
The only way I found to do that is by polluting the namespaces boost::filesystem and boost::filesystem3, then test if the original function exists. I know that's not the best thing ever, but it's a compromise to have it up and running at the end of the days.
There exist two versions of copy in both the namespaces. They are declared as:
void copy(const path& from, const path& to);
void copy(const path& from, const path& to, system::error_code& ec);
Note that I redeclared them with slightly different forms in the example below to simplify things up and to avoid using boost in the example code.
Here is a minimal, working example:
#include<iostream>
#include<type_traits>
// original namespaces
namespace boost { namespace filesystem {
void copy(int, char) { std::cout << "b::f::copy" << std::endl; }
void copy(int, char, double) {}
// ... everything else ...
}}
namespace boost { namespace filesystem3 {
void copy(int, char) { std::cout << "b::f3::copy" << std::endl; }
void copy(int, char, double) {}
// ... everything else ...
}}
// pollution
namespace boost { namespace filesystem {
struct tag {};
void copy(tag, tag) {}
}}
namespace boost { namespace filesystem3 {
struct tag {};
void copy(tag, tag) {}
}}
std::true_type test(int, void(*)(int, char));
std::false_type test(...);
constexpr bool has_filesystem_copy = decltype(test(0, &boost::filesystem::copy))::value;
constexpr bool has_filesystem3_copy = decltype(test(0, &boost::filesystem3::copy))::value;
template<bool = true>
struct fallback_fn {};
template<>
struct fallback_fn<has_filesystem3_copy> {
template<typename... Args>
static void invoke(Args... args) {
boost::filesystem3::copy(args...);
}
};
template<bool = true>
struct copy_fn: fallback_fn<> {};
template<>
struct copy_fn<has_filesystem_copy> {
template<typename... Args>
static void invoke(Args... args) {
boost::filesystem::copy(args...);
}
};
int main() {
copy_fn<>::invoke(0, 'c');
}
Feel free to play with the functions that are part of those namespaces marked as original namespaces.
To sum up:
If copy is available both in boost::filesystem and boost::filesystem3, the former is picked up. See it on wandbox.
If copy is available only in boost::filesystem, it's picked up. See it on wandbox.
If copy is available only in boost::filesystem3, it's picked up. See it on wandbox.
If copy isn't available at all, you get a compile-time error like this:
'invoke' is not a member of 'copy_fn<>'
See it on wandbox.
To do that I used the rules of template specialization and a couple of constexpr variables.
Note that you can avoid to include <type_traits> by doing this, if you prefer:
constexpr bool test(int, void(*)(int, char)) { return true; }
constexpr bool test(...) { return false; }
constexpr bool has_filesystem_copy = test(0, &boost::filesystem::copy);
constexpr bool has_filesystem3_copy = test(0, &boost::filesystem3::copy);
Again, polluting a namespace isn't the best idea with which you can come up. Anyway it's a viable approach that probably works in this case, as long as you invoke copy through an utility class like copy_fn.
As a side note, keep in mind that it's quite annoying and error-prone if you have to wrap more than one function. It's not the case if I look at the text of your question only, but I don't know what's the real case.

Here's another idea that (mostly) does the trick:
#include <tuple>
#include <utility>
#include <iostream>
namespace fake_boost {
namespace filesystem {
// class path { public:
// template<typename Source> path(Source const&) {}
// };
// void copy( const path&, const path& )
// { std::cout << "fake_boost::filesystem::copy\n"; }
}
namespace filesystem3 {
class path { public:
template<typename Source> path(Source const&) {}
};
void copy( const path&, const path& )
{ std::cout << "fake_boost::filesystem3::copy\n"; }
}
}
namespace test_copy {
template <typename...> using void_t = void; // or use C++17 std::void_t
namespace test_filesystem3 {
using namespace fake_boost::filesystem3;
template <typename... Args>
void do_copy(Args&& ... args)
{ copy(std::forward<Args>(args)...); }
}
namespace test_filesystem {
template <typename Tuple, typename Enable=void>
struct copy_switcher {
template <typename... Args>
static void do_copy(Args&& ... args)
{ test_filesystem3::do_copy(std::forward<Args>(args)...); }
};
using namespace fake_boost::filesystem;
template <typename... Args>
struct copy_switcher<std::tuple<Args...>,
void_t<decltype(copy(std::declval<Args&&>()...))>> {
static void do_copy(Args&& ... args)
{ copy(std::forward<Args>(args)...); }
};
}
}
template <typename... Args>
void do_copy(Args&& ... args) {
test_copy::test_filesystem::copy_switcher<std::tuple<Args...>>
::do_copy(std::forward<Args>(args)...);
}
int main() {
do_copy( "from.txt", "to.txt" );
}
A couple of caveats: The namespaces must actually exist, but you can always define them as empty. The function tested for must not exist at global scope with compatible arguments. In particular, you couldn't rename my last do_copy to just copy.

Related

Perfect forwarding of C++ overloaded and templated functors and its arguments

Suppose we have a function that looks like:
template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}
This works for simple non-templated functions. However, I am trying to perfect-forward a templated function(a quite contrived one):
namespace detail {
template <typename CodecImpl>
class codec
{
public:
//
// Encoding
// Convenient version, returns an std::string.
static std::string encode(const uint8_t* binary, size_t binary_size);
static std::string encode(const char* binary, size_t binary_size);
...
};
class base64_rfc4648
{
public:
template <typename Codec> using codec_impl = stream_codec<Codec, base64_rfc4648>;
static CPPCODEC_ALWAYS_INLINE constexpr size_t alphabet_size() {
static_assert(sizeof(base64_rfc4648_alphabet) == 64, "base64 alphabet must have 64 values");
return sizeof(base64_rfc4648_alphabet);
}
static CPPCODEC_ALWAYS_INLINE constexpr char symbol(alphabet_index_t idx)
{
return base64_rfc4648_alphabet[idx];
}
...
};
} // namespace detail
using base64_rfc4648 = detail::codec<detail::base64<detail::base64_rfc4648>>;
Trying to forward the above:
std::string buf("hello world");
execute(base64_rfc4648::encode, buf.c_str(), buf.size());
Does not work. Template deduction fails:
note: couldn't deduce template parameter 'F'
and it also notes:
No matching function for call to 'execute(<unresolved overloaded function type>, const char*, std::__cxx11::basic_string<char>::size_type)'
How can I fix this?
NOTE: I kept the information short above for readability, but if more info is needed I can add.
I have created a MCVE to work on the problem, rather than the code.
So let us have a generic function called print() which we want to send to your execute()
template <typename Arg>
inline void print(Arg const & a) {
std::cout << a << std::endl;
}
where execute() is:
template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}
When we try to call execute(print, 10) it fails.
The problem is that the execute() function doesn't understand which overload of print are we trying to call.
Now this problem can be solved in 2 ways :
First approach, specify the complete type of the templated function :
execute(print<int>, 10);
Second approach, create a helper function.
Every problem can be solved by adding one more layer.
This helper function will help us deduce the types, before we pass it to execute()
template <typename Arg>
inline void execute_print(Arg const & a) {
execute(print<Arg>, a); // we need to specify which overload to be invoked
}
And then you can call : execute_print(20);
Here is a full working code for your reference(compiled using C++11):
#include <string>
#include <iostream>
template <typename Arg>
inline void print(Arg const & a) {
std::cout << a << std::endl;
}
template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}
template <typename Arg>
inline void execute_print(Arg const & a) {
execute(print<Arg>, a); // we need to specify which overload to be invoked
}
int main() {
// execute(print, 5); // wont compile
execute(print<int>, 10);
execute_print(20);
return 0;
}
You can simply use boost::hof to wrap base64_rfc4648::encode in a function object.
execute(BOOST_HOF_LIFT(base64_rfc4648::encode), buf.c_str(), buf.size());
Here is the doc of BOOST_HOF_LIFT

C++ MSVC/GCC/Clang compilers bug

I discovered what appears to be a mind breaking bug in the 3 compilers from the title. The following code compiles with the latest versions of all three compilers using both the c++11 and c++14 standards, even though it really shouldn't as the "visit_detail" function is not visible to "main".
Correction: I was stupid, not actually a bug in GCC/Clang, seems to be a bug in my MSVC version tho.
#include <utility>
#include <iostream>
#include <type_traits>
namespace bug
{
using namespace std;
using size_t = unsigned long long;
namespace detail
{
struct visit_stop_t {};
constexpr bug::detail::visit_stop_t visit_stop = bug::detail::visit_stop_t();
template <typename Visitor, typename First, typename... Tail>
void visit_detail(Visitor&& vis, First&& first, Tail&&... tail)
{
// code, not necessairy to recreate bug
}
}
template <typename Visitor, typename... Variants>
void visit(Visitor&& vis, Variants&&... vars)
{
bug::detail::visit_detail(bug::forward<Visitor>(vis), bug::forward<Variants>(vars)..., bug::detail::visit_stop);
}
template <typename Visitor>
void visit(Visitor&& vis) = delete;
}
using namespace bug;
// dummy variant, used to test the code
// code is never actually used in this version
template <typename... T>
struct variant
{
static constexpr bug::size_t size() noexcept { return sizeof...(T); }
constexpr variant(int) noexcept {}
template <bug::size_t I>
constexpr int get() const noexcept { return 5; }
};
// simple example visitor
// code is never actually used in this version
struct visitor
{
int operator()(int x) { std::cout << x << std::endl; return x; }
double operator()(double x) { std::cout << x << std::endl; return x; }
};
int main()
{
visitor vis;
variant<int, double> var = 5;
// where the trouble is:
visit_detail(vis, var, bug::detail::visit_stop); // ADL: http://en.cppreference.com/w/cpp/language/adl
visit_detail(vis, var); // fails with GCC/Clang, no error with MSVC => MSVC bug maybe
std::cout << "Press enter to continue . . . ";
std::getchar();
return 0;
}
What you're experiencing is a C++ feature called argument-dependent lookup, or ADL for short. Basically, if you invoke a function f without explicitly qualifying it, the compiler will look for f in the namespaces of the arguments that you've passed.
This is what allows operator<< for IO streams to work without requiring qualifications:
std::cout << 100; // finds std::operator<<(std::ostream&, int);
In your particular case, the argument bug::detail::visit_stop is making the compiler look for visit_detail inside the bug::detail namespace.

Is it legal to specialize std library functions for a shared_ptr of a user defined type?

The standard says the following about specializing templates from the standard library (via What can and can't I specialize in the std namespace? )
A program may add a template
specialization for any standard library template to namespace std only
if the declaration depends on a user-defined type and the
specialization meets the standard library requirements for the
original template and is not explicitly prohibited.
Is it legal to specialize standard library templates with a standard library class specialized with a user defined class?
For example, specializing std::hash for std::shared_ptr<MyType>?
From reading the above paragraph and linked question, it sounds like it should be, as the declaration of the specialization is dependent on MyType, however "Unless explicitly prohibited" worries me slightly.
The example below compiles and works as expected (AppleClang 7.3), but is it legal?
#include <unordered_set>
#include <memory>
#include <cassert>
#include <string>
struct MyType {
MyType(std::string id) : id(id) {}
std::string id;
};
namespace std {
template<>
struct hash<shared_ptr<MyType>> {
size_t operator()(shared_ptr<MyType> const& mine) const {
return hash<string>()(mine->id);
}
};
template<>
struct equal_to<shared_ptr<MyType>> {
bool operator()(shared_ptr<MyType> const& lhs, shared_ptr<MyType> const& rhs ) const {
return lhs->id == rhs->id;
}
};
}
int main() {
std::unordered_set<std::shared_ptr<MyType>> mySet;
auto resultA = mySet.emplace(std::make_shared<MyType>("A"));
auto resultB = mySet.emplace(std::make_shared<MyType>("B"));
auto resultA2 = mySet.emplace(std::make_shared<MyType>("A"));
assert(resultA.second);
assert(resultB.second);
assert(!resultA2.second);
}
Yes, that is legal.
It is even questionably legal to specialize for std::shared_ptr<int> at one point; I don't know if they patched that ambiguity in the standard as a defect or not.
Note that that is a poor implemenation of a hash for global use. First, because it doesn't support null shared pointers. Second, because hashing a shared pointer as always the int value is questionable. It is even dangerous, because if a shared pointer to an int in a container has that int change, you just broke the program.
Consider making your own hasher for these kind of cases.
namespace notstd {
template<class T, class=void>
struct hasher_impl:std::hash<T>{};
namespace adl_helper {
template<class T>
std::size_t hash( T const& t, ... ) {
return ::notstd::hasher_impl<T>{}(t);
}
};
namespace adl_helper2 {
template<class T>
std::size_t hash_helper(T const& t) {
using ::notstd::adl_helper::hash;
return hash(t);
}
}
template<class T>
std::size_t hash(T const& t) {
return ::notstd::adl_helper2::hash_helper(t);
}
struct hasher {
template<class T>
std::size_t operator()(T const& t)const {
return hash(t);
}
};
}
Now this permits 3 points of customization.
First, if you override std::size_t hash(T const&) in the namespace containing T, it picks it up.
Failing that, if you specialize notstd::hasher_impl<T, void> for your type T, it picks it up.
Third, if both of those fail, it invokes std::hash<T>, picking up any specializations.
Then you can do:
std::unordered_set<std::shared_ptr<MyType>, ::notstd::hasher> mySet;
and add:
struct MyType {
MyType(std::string id) : id(id) {}
std::string id;
friend std::size_t hash( MyType const& self) {
return ::notstd::hash(self.id);
}
friend std::size_t hash( std::shared_ptr<MyType> const& self) {
if (!self) return 0;
return ::notstd::hash(*self);
}
};
which should give you a smart hash on on shared_ptr<MyType>.
This keeps the danger that someone changes id on a shared_ptr<MyType> which breaks every container containing the shared_ptr<MyType> in a non-local manner.
Shared state is the devil; consider writing a copy on write pointer if you are really worried about copying these things being expensive.

Translating a std::tuple into a template parameter pack

I have a
typedef std::tuple<A, B> TupleType;
and would like to use the list of classes
for a "template".
Suppose I have:
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
and that I can successfully use it with:
auto my_tuple = parse<A, B>(ifs);
is it possible to avoid having to specify the class list A,B if I already have a
typedef std::tuple<A,B> TupleType;
where the list A,B is already present?
an example:
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> // std::cerr
#include <fstream> // std::ifstream
#include <tuple> // std::tuple
class A {
public:
A(std::istream &); // May throw FooBaarException
};
class B {
public:
B(std::istream &); // May throw FooBaarException
};
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
int main() {
std::ifstream ifs;
ifs.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
int res = EXIT_FAILURE;
try {
ifs.open("/some/file/path", std::ios::in | std::ios::binary);
auto my_tuple = parse<A, B>(ifs); // my_tuple is of the type std::tuple<A,B>
/* Here do something interesting with my_tuple */
res = EXIT_SUCCESS;
} catch (ifstream::failure e) {
std::cerr << "error: opening or reading file failed\n";
} catch (FooBaarException e) {
std::cerr << "error: parsing in a constructor failed\n";
}
return res;
}
The underlying problem in your situation seems to be that you'd like to specialize the function template parse for the special case when the template argument is a std::tuple. Unfortunately, this kind of specialization isn't possible with function templates.
However, it is possible with class templates.
So, as a first step, you could define parse as a static function of a struct, like this:
using std::istream;
using std::tuple;
using std::make_tuple;
struct A { A(const istream &) {} };
struct B { B(const istream &) {} };
template <typename... Args>
struct parser
{
/* Your original function, now inside a struct.
I'm using direct tuple construction and an
initializer list to circumvent the order-of-
construction problem mentioned in the comment
to your question. */
static tuple<Args...> parse(const istream &strm)
{ return tuple<Args...> {Args(strm)...}; }
};
template <typename... Args>
struct parser<tuple<Args...>>
{
/* Specialized for tuple. */
static tuple<Args...> parse(const istream &strm)
{ return parser<Args...>::parse(strm); }
};
You can then call it in the desired way:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parser<tuple_type>::parse(std::cin);
return 0;
}
As a second step, you can define a function template (again) which passes the arguments on to the right specialization of the struct:
template <typename... Args>
auto parse(const istream &strm) -> decltype(parser<Args...>::parse(strm))
{ return parser<Args...>::parse(strm); }
And now you can use it in exactly the way you wanted:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parse<tuple_type>(std::cin);
return 0;
}
(And you can still use it in the old way, too: auto tup = parse<A,B>(std::cin).)
Remark. As mentioned in the comment to parser::parse(), I used direct tuple construction instead of make_tuple to avoid problems with the order of construction of the tuple elements. This is not directly related to your question, but a good thing to do. See how to avoid undefined execution order for the constructors when using std::make_tuple.
There is a standard idiom for this kind of thing. [1]
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
// ... inside here, you have access to the parameter pac
}
Here's an example of using it, which might or might not fit your expectations (your example doesn't really indicate your expected use, since it lacks the typedef you promise in your question): liveworkspace.org.
Since litb raised the point, it is possible to force the tuple-components to be constructed in left-to-right order, illustrating another interesting idiom: comb inheritance. See lws.
(Since lws might disappear again, who knows, I'll paste the code here as well):
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
type value;
template<typename Arg>
TupleMap(Arg&& arg)
: value(T(std::forward<Arg>(arg))...) {
}
operator type() { return value; }
};
//Try it out:
using std::get; // Note 2
using Numbers = std::tuple<char, double, int>;
// Note 3
std::ostream& operator<<(std::ostream& out, const Numbers& n) {
return out << get<0>(n) << ' ' << get<1>(n) << ' ' << get<2>(n);
}
int main() {
std::cout << TupleMap<Numbers>(93.14159);
return 0;
}
[1] At least, I think it's a standard idiom. I use it a lot, and think of it as the "can-opener" pattern.
[2] This is needed (or at least, it's my style) to allow the use of get with tuple-like templates defined outside of std. Doing it this way allows ADL to find the appropriate definition of get without forcing me to add specializations to std::get. In this way, it's similar to the standard ADL idiom for begin and end.
[3] You can search SO for a cool hack to specialize operator<< for all tuples. There's a simpler one which can be used for specific tuples, but that's all off-topic for this question, so I just did something easy and dependency free. Note that this works because of the conversion operator in TupleMap
The basic approach is to create a sequence of indices 0, ..., std::tuple_size<Tuple>::value - 1 as a parameter pack Indices and call your function with parse<typename std::tuple_element<Tuple, Indices>::type...>(stream). You'd probably encapsulate the logic into a function parse_tuple<Tuple>(stream) (and some function this one delegates to) which in the end delegates to parse<...>(stream).
First, here is a class template and a function to create a sequence of indices based on the size of a std::tuple. The indices are needed to obtain a list of type from std::tuple:
template <int... Indices> struct indices;
template <>
struct indices<-1> { // for an empty std::tuple<> there is no entry
typedef indices<> type;
};
template <int... Indices>
struct indices<0, Indices...> { // stop the recursion when 0 is reached
typedef indices<0, Indices...> type;
};
template <int Index, int... Indices>
struct indices<Index, Indices...> { // recursively build a sequence of indices
typedef typename indices<Index - 1, Index, Indices...>::type type;
};
template <typename T>
typename indices<std::tuple_size<T>::value - 1>::type const*
make_indices() {
return 0;
}
With this in place, it is quite easy to extract the sequence of types from a std::tuple<T...>:
template<typename T, int... Indices>
T parse_tuple(std::istream &stream, indices<Indices...> const*) {
return parse<typename std::tuple_element<Indices, T>::type...>(stream);
}
template <typename T>
T parse_tuple(std::istream& stream) {
return parse_tuple<T>(stream, make_indices<T>());
}

C++0x Lambda to function pointer in VS 2010

I am trying to use a lambda to pass in place of a function pointer but VS2010 can't seem to convert it. I have tried using std::function like this and it crashes and I have no idea if I am doing this right!
#include <windows.h>
#include <conio.h>
#include <functional>
#include <iostream>
#include <concrt.h>
void main()
{
std::function<void(void*)> f = [](void*) -> void
{
std::cout << "Hello\n";
};
Concurrency::CurrentScheduler::ScheduleTask(f.target<void(void*)>(), 0);
getch();
}
It seems strange to me that the compiler can't convert such a lambda to a simple function pointer as it captures no variables - also in the case that it did I wonder what can be done.
Is the type of each lambda unique? So I could hack around with a template function using the lambdas' type as a template argument to generate a unique static function that could be called instead and hopefully optimised out?
UPDATED
The below seems to work but is it safe?
#include <windows.h>
#include <conio.h>
#include <iostream>
#include <concrt.h>
template<typename Signature>
struct Bind
{
static Signature method;
static void Call(void* parameter)
{
method(parameter);
}
};
template<typename Signature>
Signature Bind<Signature>::method;
template<typename Signature>
void ScheduleTask(Signature method)
{
Bind<Signature>::method = method;
Concurrency::CurrentScheduler::ScheduleTask(&Bind<Signature>::Call,0);
}
void main()
{
ScheduleTask
(
[](void*)
{
std::cout << "Hello";
}
);
ScheduleTask
(
[](void*)
{
std::cout << " there!\n";
}
);
getch();
}
UPDATED AGAIN
So with the help given I have come up with the shorter:
template<typename Signature>
void (*LambdaBind(Signature))(void*)
{
struct Detail
{
static void Bind(void* parameter)
{
Signature method;
method(parameter);
}
};
return &Detail::Bind;
}
This can be used to wrap a lambda with no closure of void(*)(void*) into the equivalent function pointer. It appears that this will become unnecessary in a later version of VS2010.
So how to get this to work for a lambda with closures?
UPDATED AGAIN!
Works for closures in VS2010 - no idea if it's 'safe' though...
template<typename Signature>
struct Detail2
{
static std::function<void(void*)> method;
static void Bind(void* parameter)
{
method(parameter);
}
};
template<typename Signature>
std::function<void(void*)> Detail2<Signature>::method;
template<typename Signature>
void (*LambdaBind2(Signature method))(void*)
{
Detail2<Signature>::method = method;
return &Detail2<Signature>::Bind;
}
This feature of lambda's was added after VS2010 implemented them, so they don't exist in it yet.
Here's a possible generic work-around, very untested:
#include <functional>
#include <iostream>
namespace detail
{
// helper specializations,
// define forwarding methods
template <typename Lambda, typename Func>
struct lambda_wrapper;
#define DEFINE_OPERATOR \
typedef decltype(&call) function_type; \
operator function_type(void) const \
{ \
return &call; \
}
template <typename Lambda, typename C, typename R>
struct lambda_wrapper<Lambda, R (C::*)(void) const>
{
static R call(void)
{
Lambda x;
return x();
}
DEFINE_OPERATOR
};
template <typename Lambda, typename C, typename R,
typename A0>
struct lambda_wrapper<Lambda, R (C::*)(A0) const>
{
static R call(A0&& p0)
{
Lambda x;
return x(std::forward<A0>(p0));
}
DEFINE_OPERATOR
};
// and so on
#undef DEFINE_OPERATOR
}
// wraps a lambda and provides
// a way to call it statically
template <typename Lambda>
struct lambda_wrapper :
detail::lambda_wrapper<Lambda, decltype(&Lambda::operator())>
{};
template <typename Lambda>
lambda_wrapper<Lambda> wrap_lambda(const Lambda&)
{
return lambda_wrapper<Lambda>();
}
int main(void)
{
auto l = [](){ std::cout << "im broked :(" << std::endl; };
std::function<void(void)> f = wrap_lambda(l);
f();
}
Let me know if any part is confusing.
If scheduling lambdas/function objects in Concurrency::CurrentScheduler is what you want, it may be worth your while looking at ConcRT Sample Pack v0.32 here
The task_scheduler struct can schedule lambdas asynchronously, but be advised, passing by reference may cause bad things to happen (since we are talking about asynchronous scheduling without a join/wait, a reference on the stack may no longer be valid at time of task execution!)