将模板函数转换为通用Lambda [英] Convert template function to generic lambda

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

问题描述

我想像模板化函数那样传递模板化函数,但这不起作用。

I'd like to pass templated functions around as if they were generic lambdas, however this does not work.

#include <iostream>
#include <vector>
#include <tuple>
#include <string>
#include <utility> 


// for_each with std::tuple
// (from https://stackoverflow.com/a/6894436/1583122)
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(std::tuple<Tp...> &, FuncT)
{}

template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT f) {
    f(std::get<I>(t));
    for_each<I + 1, FuncT, Tp...>(t, f);
}

// my code
template<class T> auto
print(const std::vector<T>& v) -> void {
    for (const auto& e : v) {
        std::cout << e << "\t";
    }
}

struct print_wrapper {
    template<class T>
    auto operator()(const std::vector<T>& v) {
        print(v);
    }
};

auto print_gen_lambda = [](const auto& v){ print(v); };

auto print_gen_lambda_2 = []<class T>(const std::vector<T>& v){ print(v); }; // proposal P0428R1, gcc extension in c++14/c++17

int main() {
     std::tuple<std::vector<int>,std::vector<double>,std::vector<std::string>> t = { {42,43},{3.14,2.7},{"Hello","World"}};
    for_each(t, print); // case 1: error: template argument deduction/substitution failed: couldn't deduce template parameter 'FuncT'
    for_each(t, print_wrapper()); // case 2: ok
    for_each(t, print_gen_lambda); // case 3: ok
    for_each(t, print_gen_lambda_2); // case 4: ok
}

请注意,情况2和4严格等效。情况3更一般,但不受限制(这对我来说是个问题)。我认为用语言应将情况1与情况2和4等效,但是情况并非如此。

Note that case 2 and 4 are strictly equivalent. Case 3 is more general but unconstrained (this is a problem for me). I think that case 1 should be treated equivalently to cases 2 and 4 by the language, however this is not the case.


  • 提议将模板函数隐式转换为通用约束的lambda(案例2/4)?如果没有,那么是否有根本的语言原因阻止这样做?

  • 到目前为止,我必须使用情况2,这很麻烦。


    • 情况4:不符合c ++ 14,即使在 c ++ 20 ,但仍然不够完美(冗长,因为您创建的Lambda基本上可以不添加任何信息。)

    • 情况3:不受约束,但我依靠(此处未显示)对使用非 vector参数调用 print的替换失败(P0428R1提到这个问题)。因此,我猜想附属的问题是我可以使用一些enable_if技巧来约束通用lambda吗?

    • Is there a proposal to implicitly convert a template function to a generic constrained lambda (case 2/4)? If no, is there a fundamental language reason that prevents from doing so?
    • As of now, I have to use case 2, which is quite cumbersome.
      • case 4: not c++14-compliant, even if should be standard in c++20, and still not perfect (verbose since you create a lambda that fundamentally does not add any information).
      • case 3: is unconstrained, but I rely (not shown here) on substitution failure for calls to "print" with non-"vector" arguments (P0428R1 mentions this problem). So I guess the subsidiary question is "Can I constrain a generic lambda with some enable_if tricks?"

      在C ++ 14/17/20中,是否存在一种非常简洁的方式来实现从案例1到案例2的转换?我什至对宏黑客持开放态度。

      Is there, in C++14/17/20, a very terse manner to enable the conversion from case 1 to case 2? I am even open to macro hacks.

      推荐答案


      在C ++ 14/17中存在/ 20,这是一种非常简洁的方式,可实现从案例1到案例2的转换?我什至对宏黑客持开放态度。

      Is there, in C++14/17/20, a very terse manner to enable the conversion from case 1 to case 2? I am even open to macro hacks.

      是。

      // C++ requires you to type out the same function body three times to obtain
      // SFINAE-friendliness and noexcept-correctness. That's unacceptable.
      #define RETURNS(...) noexcept(noexcept(__VA_ARGS__)) \
           -> decltype(__VA_ARGS__){ return __VA_ARGS__; }
      
      // The name of overload sets can be legally used as part of a function call -
      // we can use a macro to create a lambda for us that "lifts" the overload set
      // into a function object.
      #define LIFT(f) [](auto&&... xs) RETURNS(f(::std::forward<decltype(xs)>(xs)...))
      

      然后您可以说:

      for_each(t, LIFT(print)); 
      








      是否有提议将模板函数隐式转换为通用约束的lambda?

      Is there a proposal to implicitly convert a template function to a generic constrained lambda?

      是的,请查看 P0119 N3617 。不确定其状态。

      Yes, look at P0119 or N3617. Not sure about their status.

      这篇关于将模板函数转换为通用Lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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