Can Std::Is_Invocable Be Emulated Within C++11

Can std::is_invocable be emulated within C++11?

You can try this implementation:) Taken from boost C++ libraries. I've tested it with VS2017 with standard C++14.

template <typename F, typename... Args>
struct is_invocable :
std::is_constructible<
std::function<void(Args ...)>,
std::reference_wrapper<typename std::remove_reference<F>::type>
>
{
};

template <typename R, typename F, typename... Args>
struct is_invocable_r :
std::is_constructible<
std::function<R(Args ...)>,
std::reference_wrapper<typename std::remove_reference<F>::type>
>
{
};

How can I Tell if a Type is a Functor?

Yes you can, std::is_invocable is a library function which requires no compiler support. You can just rip the implementation from an STL of your choice.

For example, you can find LLVM implementation of __invokable (to which std::is_invocable forwards all the logic in LLVM's STL) here: https://android.googlesource.com/platform/ndk/+/5b3a49bdbd08775d0e6f9727221fe98946f6db44/sources/cxx-stl/llvm-libc++/libcxx/include/type_traits

(I was thinking of extracting it and posting here, but it seems to be too big for a post. On a lighter note, I find difference in spelling - invocable vs invokable - amusing.)

Find out whether a C++ object is callable

I think this trait does what you want. It detects operator() with any kind of signature even if it's overloaded and also if it's templatized:

template<typename T>
struct is_callable {
private:
typedef char(&yes)[1];
typedef char(&no)[2];

struct Fallback { void operator()(); };
struct Derived : T, Fallback { };

template<typename U, U> struct Check;

template<typename>
static yes test(...);

template<typename C>
static no test(Check<void (Fallback::*)(), &C::operator()>*);

public:
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
};

The principle is based on Member Detector idiom. As it is, it will fail to compile if you pass it a non-class type, but that shouldn't be hard to fix, I just left it out for brevity. You can also extend it to report true for functions.

Of course it doesn't give you any info about the signature(s) of operator() whatsoever, but I believe that's not what you asked for, right?

EDIT for Klaim:

It's simple enough to make it work (return false) with non-class types. If you rename the above class to is_callable_impl, you can write this, for example:

template<typename T>
struct is_callable
: std::conditional<
std::is_class<T>::value,
is_callable_impl<T>,
std::false_type
>::type
{ };

candidate template ignored: could not match 'functiontype-parameter-0-0 ()' against 'double (*)()'

It cannot be deduced because you are not passing a std::function to funcCxx.

Function argument and parameter type must match in template argument deduction. Otherwise deduction fails.

You could let the function take any type instead of constraining it to function pointers or std::function and then you can construct the std::function inside the function:

template <typename V>
void funcCxx (V&& v){
auto f = std::function(std::forward<V>(v));
std::cout << "C++ function's value is\"" << f() << '\"' << std::endl;
}

C++ template function, specify argument type of callback functor/lambda while still allow inlining?

If you have C++20 that's is exactly what the concepts are for

#include <concepts>

template<typename T>
concept Callback = requires(T a) {
{ a(int()) } -> std::same_as<void>;
};

template<Callback T>
void some_func(T const& callback){
// ....
}

int a(int) {
return 0;
}

void b(int) {}

int main() {
// below does not compile
// some_func(a);
some_func(b);
}

Is there a way to extract a dict in Python into the local namespace?

Since it is not safe to modify the dict that locals() returns

>>> d={'a':6, 'b':"hello", 'c':set()}
>>> exec '\n'.join("%s=%r"%i for i in d.items())
>>> a
6
>>> b
'hello'
>>> c
set([])

But using exec like this is ugly. You should redesign so you don't need to dynamically add to your local namespace

Edit: See Mike's reservations about using repr in the comments.

>>> d={'a':6, 'b':"hello", 'c':set()}
>>> exec '\n'.join("%s=d['%s']"%(k,k) for k in d)
>>> id(d['c'])
3079176684L
>>> id(c)
3079176684L


Related Topics



Leave a reply



Submit