是否可以弄清楚多态C ++ 14 lambda的参数类型和返回类型? [英] Is it possible to figure out the parameter type and return type of a polymorphic C++ 14 lambda?

查看:95
本文介绍了是否可以弄清楚多态C ++ 14 lambda的参数类型和返回类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从此问题开始(

Starting from this question (Is it possible to figure out the parameter type and return type of a lambda?) I used the proposed function_traits a lot. However, with C++14 polymorphic lambdas have arrived and they gave me a hard time.

template <typename T>
struct function_traits
    : public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
    enum { arity = sizeof...(Args) };
    // arity is the number of arguments.

    typedef ReturnType result_type;

    template <size_t i>
    struct arg
    {
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
        // the i-th argument is equivalent to the i-th tuple element of a tuple
        // composed of those arguments.
    };
};

另一个问题的答案中提出的operator()现在已超载,如标准中所述以支持:

The operator() as proposed in the other question's answer is now overloaded as stated in the standard to support:

auto lambda1 = [](auto& a) { a.foo(); } 

auto lambda2 = [](auto&&... args) { foo(args...); };

此重载现在将function_traits类撕裂了,因为编译器无法解析operator()的正确版本.

This overloading now rips the function_traits class apart because the compiler cannot resolve the correct version of operator().

lambda.cpp:98:38: error: reference to overloaded function could not be
      resolved; did you mean to call it?
      typedef function_traits<decltype(&T::operator())> caller;

是否可以通过C ++ 14在多态lambda上实现function_traits的功能?

Is it somehow possible to achieve the functionality of function_traits on polymorphic lambdas with C++14?

推荐答案

使用 Fetch函数实现 Cache 时,我遇到了类似的情况 . 像这样:

I had a similar case when implementing a Cache with a Fetch function. Something like:

template<class KEY, class VALUE, class FetchFunctor>
class Cache { ... };


阶段1

我希望为用户省去陈述他/她的 FetchFunctor 类型的需要,而无需使用


Phase 1

I wanted to save the user the need to state the type of his/her FetchFunctor and without the C++17 class template argument deduction I went for a createCahce helper method like this:

// [1]
template<class KEY, class VALUE, class FetchFunctor>
auto createCache(FetchFunctor fetchFunctor) {
    return Cache<KEY, VALUE, FetchFunctor>(fetchFunctor);
}

因此创建缓存非常简单,例如:

Thus creating the cache is quite easy, e.g.:

auto cache = createCache<int, int>([](int i){return i+3;});


第二阶段

允许用户无需提供 Key Value 而创建缓存的做法会更好. strong>类型的缓存,并从提供的 FetchFunctor 中推断出它们.因此,我添加了一个附加的 createCache 方法:


Phase 2

It would be much nicer to allow the user creating a cache without the need to provide the Key and Value types of the cache and to deduce them both from the provided FetchFunctor. So I added an additional createCache method:

// [2]
template<class FetchFunctor>
auto createCache(FetchFunctor fetchFunctor) {
    // function_traits is a namespace where I 'hide' the
    // traits structs for result type and arguments type deduction
    using f = function_traits::traits<decltype(fetchFunctor)>;
    using KEY = typename f::template arg<0>::type;
    using VALUE = typename f::result_type;
    return Cache<KEY, VALUE, FetchFunctor>(fetchFunctor);
}

现在创建缓存更加简单:

Now creating the cache is even easier:

auto cache = createCache([](int i){return i+3;});


但是,上面的两个"createCache"方法都可以一起生活吗?

幸运的是.


But, can both 'createCache' methods above live together?

Luckily yes.

  1. 如果用户提供模板参数键,值,则第一个是唯一匹配项.
  2. 如果用户不提供模板参数,则编译器会将第二个参数视为更专业化" ,并将更喜欢它.
  1. If the user provides the template arguments Key, Value then the first one is the only match.
  2. If the user doesn't provide the template arguments, the compiler considers the second one as 'more specialized' and will prefer it.

这样,我们可以支持以下所有情况:

This way we can support all the below cases:

    // [a]
    auto cache = createCache([](int i){return i+3;});
    // compiler deduces Key, Value to be: int, int - using the 2nd createCache

    // [b]
    auto cache = createCache<int, int>([](auto i){return i+3;});
    // we have a generic lambda so we provide Key and Value - using the 1st createCache

    // [c]
    auto cache = createCache<string, string>(
        [](const char* s){return string(s) + '!';}
    );
    // we want different Key and/or Value than would be deduced - we use 1st createCache


仍然...

以下内容将无法编译:


Still...

The following will not compile:

    auto cache = createCache([](auto i){return i+3;});
    // we cannot deduce types for generic lambda
    // compiler goes to the 2nd createCache but Key and Value cannot be deduced
    // - compilation error

但这不应该困扰我们...您可以像上面的[b]中那样提供键和值.

But this shouldn't bother us... you can provide Key and Value as in [b] above.

http://coliru.stacked-crooked.com/a/e19151a5c245d7c3

这篇关于是否可以弄清楚多态C ++ 14 lambda的参数类型和返回类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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