2

我有一个元函数,它给了我I一个 lambda/函数的 -th 参数的类型:

#include <iostream>
#include <tuple>

namespace details
{
    //! Spezialization for Funktion-Pointers
    template<typename Ret, typename... Args>
    std::tuple<Args...> getArgs(Ret (*)(Args...));

    //! Spezialization for Functor/Lambdas
    template<typename F, typename Ret, typename... Args>
    std::tuple<Args...> getArgs(Ret (F::*)(Args...));

    //! Spezialization for Functor/Lambdas
    template<typename F, typename Ret, typename... Args>
    std::tuple<Args...> getArgs(Ret (F::*)(Args...) const);

}; // namespace details

template<typename F, std::size_t I>
using GetArg = std::tuple_element_t<I, decltype(details::getArgs(std::declval<F>()))>;

int main()
{
    auto f1 = [](int a, int b){};
    static_assert(std::is_same<GetArg<decltype(f1), 0>, int>{}, "Not the same!");

    // auto f2 = [](int a, auto b){};
    // static_assert(std::is_same<GetArg<decltype(f2), 0>, int>{}, "Not the same!");
}

居住

带有说明符的第二个 lambdaauto无法编译,因为我的 spezializations 不匹配,因为auto它就像一个T未知的模板参数。有没有办法让这项工作f2也有效?

由于 lambda 是一种不透明类型,并且模板函数没有类型,除非使用模板参数类型进行实例化,所以我真的不知道如何使它工作?这是不可能的吗?

4

1 回答 1

0

有没有办法让这项工作f2也有效?

不,据我所知。

您可以将通用 lambda(具有一个或多个auto参数的 lambda)几乎视为模板函数(包装在类中)。

排除类包装,你可以看到

[](int a, auto b){};

几乎一样

template <typename T>
void foo (int a, T b)
 { };

您不能b完全从 lambda 中推断出的类型,就像您无法推断出bfrom的类型一样foo():它决定调用函数(从参数中推断出类型)或解释它(类似于foo<int>)。

但是如果你只是简单地写decltype(foo),编译器就无法决定是哪种类型,T所以会报错。

无论如何,我也得到一个错误编译

static_assert(std::is_same<GetArg<decltype(f1), 0>, int>{}, "Not the same!");

我想你必须写GetArg如下

using GetArg = std::tuple_element_t<I, decltype(details::getArgs(&F::operator()))>;
// ..............................................................^^^^^^^^^^^^^^

或者你可以保持你的实际GetArg但调用它+f1

static_assert(std::is_same<GetArg<decltype(+f1), 0>, int>{}, "Not the same!");
// ........................................^^^

即:将 lambda 转换为函数指针。

于 2019-04-12T11:09:28.513 回答