如何为通用lambda参数定义模板参数? [英] How to define template parameters for a generic lambda argument?

查看:238
本文介绍了如何为通用lambda参数定义模板参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说明:

CLion,它是标准编译器,在我编写时给我一个错误,候选模板[被忽略]以lambda作为参数的泛型函数的参数,该泛型函数将lambda作为参数。
此lambda采用通用类型 T 并返回另一个未知类型 A

CLion and it's standard compiler give me an error that the "candidate template [is] ignored", when I write a lambda as parameter for a generic function that takes a lambda as argument. This lambda takes a generic type T and returns another unknown type A.

我正在编写的容器类应该支持Scala中的此类功能性操作或Java Stream API中的功能性操作。

The container class that I am writing is supposed to support functional operations like these in Scala or the ones from the Java Stream API.

确切地说:
map函数会带来很多问题。它在名为Sequence的类中作为成员函数实现,该类采用通用参数 T
应该采用一个已知类型 T 的元素(实际上会遍历整个序列)并将其转换为未知类型 A
实现本身不是问题,但是我无法使用我知道的lambda语法调用该函数。

To be exact: The map function makes huge problems. It is implemented as a member function in a class called Sequence, which takes a generic parameter T. It is supposed to take an element of an already known type T ( actually it iterates through the whole sequence ) and convert it into an unknown type A. The implementation itself is not the problem, but I cannot call the function with the lambda syntax I know.

代码:

Sequence.h

template< typename T >
class Sequence {
public:
    template< typename A >
    auto map( std::function< A( const T ) > function ) const {
        auto sequence = new Sequence< A >;
        for ( const T& element : *this ) {
            sequence->push( function( element ) );
        }
        return *sequence;
    }
}

main.cpp

int main() {
    Sequence< uint32_t > a;
    a.push( 20 );
    a.push( 30 );
    a.push( 40 );

    a.map( []( uint32_t c ) -> uint32_t {
        return c * c;
    } );
    return 0;
}

据我了解,lambda已初始化,
需要类型为 std :: uint32_t 的参数,并返回类型为 std :: uint32_t 的值。
通用参数 A 在这一点上似乎还没有得出。

As far as I understand a lambda gets initialized, which takes a parameter of type std::uint32_t and returns a value of type std::uint32_t. The generic parameter A doesn't seem to get inferred at this point.

错误堆栈:

main.cpp:21:7: error: no matching function for call to 'Sequence<unsigned int>::map(main()::<lambda(uint32_t)>)'
     } );

Sequence.h:143:10: note: candidate: template<class A> auto Sequence<T>::map(std::function<A(T)>) const [with A = A; T = unsigned int]
     auto map( std::function< A( const T ) > function ) const {

note:   template argument deduction/substitution failed:
main.cpp:21:7: note:   'main()::<lambda(uint32_t)>' is not derived from 'std::function<A(unsigned int)>'
     } );

预先感谢!

推荐答案

正如@cpplearner在上面的注释中已经指出的,此操作不起作用的原因在此处进行了详细说明:从lambda构造std :: function参数

As already pointed out by @cpplearner in the comments above, the reason why this won't work is explained in detail here: Constructing std::function argument from lambda.

如果您的Sequence已经是模板,则应该没有理由要求 map 函数的可调用对象以 std :: function 的形式传递。至少,我似乎无法提出可以证明这样做的理由。 std :: function 通常不是免费构造或调用的,还可以禁止内联。除非您确实需要存储任意可调用对象以供以后使用的功能,否则最好避免这种情况。只需添加转发参考,例如:

If your Sequence is already a template, there should be no reason to require the callable for your map function to be passed in the form of an std::function. At least, I seem unable to come up with a reason that could justify doing this. std::function is generally not free to construct or call, and also can inhibit inlining. Best avoid it unless you really need the capability to store arbitrary callables for later use. Simply take a forwarding reference, e.g.:

template <typename F>
auto map(F&& f) const;

您应该能够推断出调用 f的结果的类型在序列中的某个元素上最终产生,例如通过

You should be able to deduce the result type of whatever invoking f on an element of your sequence ends up producing, e.g., via

decltype(f(std::declval<T>()))

此外,不要仅仅返回指向新序列。使用 std :: unique_ptr

Furthermore, don't just return a raw pointer to a new Sequence. Use an std::unique_ptr.

将它们放在一起,您的地图函数可能看起来像这样:

Putting it all together, your map function could look something like this:

template <typename F>
auto map(F&& f) const
{
    using output_element_type = decltype(f(std::declval<T>()));

    auto sequence = std::make_unique<Sequence<output_element_type>>();

    for (const T& element : *this)
        sequence->push(f(element));

    return sequence;
}

这篇关于如何为通用lambda参数定义模板参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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