接受任何类型的可调用和也知道参数类型 [英] Accept any kind of callable and also know argument type

查看:89
本文介绍了接受任何类型的可调用和也知道参数类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道是否可能,所以这就是我想要找出的。



我想创建一个函数接受任何类型的函子/ callable对象,但我想知道参数类型是什么。 (但不强制执行)



所以,这一个捕获所有,但不给我的参数类型:

  template<类型名T> 
void optionA(T);

这一个捕获最多,并且具有参数的类型

  template<类型名T> 
void optionB(std :: function< void(T)>);

但这个不允许lambdas,所以

  optionB([](int){}); 

无法编译。
这有点奇怪,因为这将编译:

  std :: function< void(int)> func = [](int){}; 
optionB(func);

那么有没有办法接受所有选项,

- 编辑 -



我想这样做的原因是因为我想让我的库的用户注册一个特定类型的回调。对我来说,最自然的方式是

  auto callback = [](int val){cout< 我的回调< val<< endl; }; 
object.register(callback);

(使用或不使用回调作为中间变量)



由于我需要根据用户期望的值的类型修改行为,我需要知道他/她期望的类型。

解决方案

这里有一个例子,对于大多数可调用包括functor和lambdas(虽然不是通用函数作为@Yakk在问题的评论中演示)。



此代码在确定返回类型和多个参数时也很有用。

  template< typename T> 
struct func_traits:public func_traits< decltype(& T :: operator())> {};

template< typename C,typename Ret,typename ... Args>
struct func_traits< Ret(C :: *)(Args ...)const> {
using result_type = Ret;

template< std :: size_t i>
struct arg {
using type = typename std :: tuple_element< i,std :: tuple< Args ...>>
};
};

template< typename T>
void option(T& t){
using traits = func_traits< typename std :: decay< T> :: type> ;;

使用return_t = typename traits :: result_type; //返回类型。
使用arg0_t = typename traits :: template arg< 0> :: type; // First arg type。

//输出类型。
std :: cout<< 返回类型:<< typeid(return_t).name()<< std :: endl;
std :: cout<< 参数类型:<< typeid(arg0_t).name()< std :: endl;
}

要添加对常规功能的支持,请添加专业化,例如

 模板< typename Ret,typename ... Args> 
struct func_traits< Ret(*)(Args ...)> {/ * ... * /}

更有用的信息: a href =http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda>是可能的要找出lambda的参数类型和返回类型?


I'm not sure if it's possible, so that's what I want to find out.

I'd like to create a function which accepts any kind of functor/callable object, but I want to know what the argument type is. ( but not enforce it )

So, this one captures all but doesn't give me the type of the argument:

template < typename T >
void optionA( T );

This one captures most, and has the type of the argument

template < typename T >
void optionB( std::function< void(T) > );

But this one doesn't allow lambdas, so

optionB( [](int){} );

will not compile. Which is somewhat strange, as this will compile:

std::function< void(int) > func = [](int){};
optionB( func );

So is there a way to accept all options and also know which type of argument is expected?

thanks in advance!

-- edit --

The reason I'd like to do this comes from the fact that I want the user of my library to register a callback with a certain type. To me, the most natural way is

auto callback = []( int val ) { cout << "my callback " << val << endl; };
object.register( callback );

(with or without the use of callback as intermediate variable)

Since I need to modify the behaviour based on the type of value the user expects, I need to know what type he/she expects.

解决方案

Here's an example that will work for most callables including functors and lambdas (although not for generic functors as @Yakk demonstrated in a comment on the question).

The code can also be useful when determining return type and multiple arguments.

template <typename T>
struct func_traits : public func_traits<decltype(&T::operator())> {};

template <typename C, typename Ret, typename... Args>
struct func_traits<Ret(C::*)(Args...) const> {
    using result_type =  Ret;

    template <std::size_t i>
    struct arg {
        using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
    };
};

template <typename T>
void option(T&& t) {
    using traits = func_traits<typename std::decay<T>::type>;

    using return_t = typename traits::result_type;         // Return type.
    using arg0_t = typename traits::template arg<0>::type; // First arg type.

    // Output types.
    std::cout << "Return type: " << typeid(return_t).name() << std::endl;
    std::cout << "Argument type: " << typeid(arg0_t).name() << std::endl;
}

To add support for regular functions add a specialization e.g.

template <typename Ret, typename... Args>
struct func_traits<Ret(*)(Args...)> { /* ... */ }

More useful info: Is it possible to figure out the parameter type and return type of a lambda?

这篇关于接受任何类型的可调用和也知道参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆