c++ - How to test lambda in C++11 -
normally, test if pointer points function, use std::is_function
enough.
however, cannot work lambda. since lambda object operator()
.
now have use both is_function
, is_object
check if 1 works function, below:
std::is_function<decltype(f)>::value || std::is_object<decltype(f)>::value
so i'm wondering if there better way test if 1 lambda or not?
edit:
related code:
template<typename func> void deferjob(func f, int ms=2000) { if(! std::is_function<decltype(f)>::value && ! std::is_object<decltype(f)>::value){ qdebug()<<"not function!"; return; } qtimer* t = new qtimer; t->setsingleshot(true); qobject::connect(t, &qtimer::timeout, [&f, t](){ qdebug()<<"deferjob"; f(); t->deletelater(); }); t->start(ms); }
edit2:
similar question: c++ metafunction determine whether type callable
so here thoughts may or may not helpful.
to create type_trait works functors, lambdas , traditional functions, think seeing if template argument convertible
std::function<void()>
. think cover bases in clear way.as we've mentioned in comments, can't test template argument way doing.
f()
later in function cause compile error, , you'll never have opportunity see runtime error.you can try
std::enable_if
. you'd need create template specializations sfinae can function choose correct implementation. use type_trait mentioned in bullet 1.if did this, make implementation of other template
static_assert
create "better" error message.that being said, compiler error messages aren't bad in first place. (at least in clang , gcc. haven't looked msvc).
this doesn't great error message, different one:
#include <cassert> #include <functional> #include <type_traits> template <typename func> typename std::enable_if<std::is_convertible<func, std::function<void()>>::value>::type deferjob(func f, int ms=2000) { } void normal_function() {} int main() { deferjob([]() {}); // works deferjob(&normal_function); // works deferjob(3); // compile time error }
in clang, error looks like:
foo.cc:15:2: error: no matching function call 'deferjob' deferjob(3); // compile time error ^~~~~~~~ foo.cc:6:25: note: candidate template ignored: disabled 'enable_if' [with func = int] typename std::enable_if<std::is_convertible<func, std::function<void()>>::value>::type
in gcc, error looks like:
foo.cc: in function ‘int main()’: foo.cc:15:12: error: no matching function call ‘deferjob(int)’ deferjob(3); // compile time error ^ foo.cc:15:12: note: candidate is: foo.cc:7:1: note: template<class func> typename std::enable_if<std::is_convertible<func, std::function<void()> >::value>::type deferjob(func, int) deferjob(func f, int ms=2000) { ^ foo.cc:7:1: note: template argument deduction/substitution failed: foo.cc: in substitution of ‘template<class func> typename std::enable_if<std::is_convertible<func, std::function<void()> >::value>::type deferjob(func, int) [with func = int]’: foo.cc:15:12: required here foo.cc:7:1: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
we go 1 step further (although doing way makes hard extend further) , add additional function:
template <typename func> typename std::enable_if<not std::is_convertible<func, std::function<void()>>::value>::type deferjob(func f, int ms=2000) { static_assert(false, "you should pass function"); }
this causes clang report (at compile time):
foo.cc: in function ‘typename std::enable_if<(! std::is_convertible<func, std::function<void()> >::value)>::type deferjob(func, int)’: foo.cc:14:2: error: static assertion failed: should pass function static_assert(false, "you should pass function");
but sadly, doesn't give stack trace, find far less helpful of earlier messages.
and finally, replace static assert runtime message:
template <typename func> typename std::enable_if<not std::is_convertible<func, std::function<void()>>::value>::type deferjob(func f, int ms=2000) { qdebug() << "not function!"; }
Comments
Post a Comment