是否可以弄清楚多态C ++ 14 lambda的参数类型和返回类型? [英] Is it possible to figure out the parameter type and return type of a polymorphic 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.
- 如果用户提供模板参数键,值,则第一个是唯一匹配项.
- 如果用户不提供模板参数,则编译器会将第二个参数视为更专业化" ,并将更喜欢它.
- If the user provides the template arguments Key, Value then the first one is the only match.
- 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屋!