【问题标题】:Function object to pass std::get around as an argument to functions将 std::get 作为参数传递给函数的函数对象
【发布时间】:2021-03-20 03:02:47
【问题描述】:

我的意图是为std::get 的任何Nth 元素编写一个getter,一旦它被特定的N 实例化,它就可以作为参数。

换句话说,std::get<N> 不能被传递,因为它不是一个函数对象,而是一个根据它所接受的参数类型模板化的函数。

是否可以定义一个对象getNth 使得std::invoke(getNth<1>, whatever); 有意义并且实际上等效于getNth<1>(whatever)?

我最多可以使用std::invoke(getNth<1>(), whatever);,通过这种方式定义getNth:

template<int N>
auto getNth() {
    return [](auto const& x){ return std::get<N>(x); };
};

是否可以避免使用两个括号?

我认为模板化 lambdas 可能有用,但它们不能,因为它们是具有模板化 operator() 的类,就像通用非模板化 lambdas 一样(唯一的区别在于,我们可以将参数的类型设为模板参数的非恒等函数)。

相反,为了使std::invoke(getNth&lt;1&gt;, whatever); 有意义,我认为getNth 不应该是模板函数,也不应该是模板类,而是其他东西......在结束&gt; 之后不带括号,如它发生在variable templates。

但是,根据this page 顶部的要点,我可能正在寻找语法根本不提供的东西。是这样吗?

【问题讨论】:

    标签: c++ lambda template-meta-programming c++20 function-object


    【解决方案1】:

    在结束 &gt; 之后不带括号,因为它发生在变量模板中。

    没错,变量模板正是你想要的:

    #include <functional>
    #include <tuple>
    
    template<int N>
    auto getNth = [](auto const& x){ return std::get<N>(x); };
    
    int main() {
        auto whatever = std::tuple{1, 2, 3};
        return std::invoke(getNth<1>, whatever);
    }
    

    Demo

    【讨论】:

    • 哦,主啊,这很明显!一个 lambda 是一个变量!我现在觉得自己好傻……
    • 出于好奇,你知道有没有提供这样一个函数对象的库?
    • 我什么都不知道,真可惜。奇怪的是,在 Boost.Hana at_c 中(它是为自己的元组设计的,但可以通过适配器与 std::tuple 一起工作)“是一个重载函数,而不是函数对象。因此,它不能传递给高阶算法。这样做是出于编译时性能的原因”。 boost.org/doc/libs/1_74_0/libs/hana/doc/html/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2022-12-12
    • 2012-02-27
    • 2017-06-04
    • 1970-01-01
    相关资源
    最近更新 更多