IT story

람다 함수를 템플릿으로 만들 수 있습니까?

hot-time 2020. 4. 30. 07:32
반응형

람다 함수를 템플릿으로 만들 수 있습니까?


C ++ 11에는 람다 함수를 템플릿으로 만드는 방법이 있습니까? 아니면 템플릿으로 지정하기에는 너무 구체적입니까?

대신 고전적인 템플릿 클래스 / 함수를 정의 할 수 있다는 것을 이해하지만 질문은 더 비슷합니다. 언어가 람다 함수를 템플릿 화 할 수 있습니까?


업데이트 2018 : C ++ 20에는 템플릿 및 개념화 된 람다가 제공됩니다. 이 기능은 이미 표준 초안에 통합되었습니다.


업데이트 2014 : C ++ 14가 올해 릴리스되었으며 이제이 예제와 동일한 구문으로 다형성 람다를 제공합니다. 일부 주요 컴파일러는 이미이를 구현합니다.


그것은 C ++ 11에서 슬프게도 아닙니다. 다형성 람다는 유연성과 힘면에서 우수합니다.

그들이 단일 형태가 된 최초의 이유는 개념 때문이었습니다. 개념으로 인해이 코드 상황이 어려워졌습니다.

template <Constraint T>
void foo(T x)
{
    auto bar = [](auto x){}; // imaginary syntax
}

제한된 템플릿에서는 다른 제한된 템플릿 만 호출 할 수 있습니다. (그렇지 않으면 제약 조건을 확인할 수 없습니다.) foo호출 할 수 있습니까 bar(x)? 람다에는 어떤 제약 조건이 있습니까 (매개 변수는 템플릿 일뿐입니다)?

개념은 이런 종류의 일을 다룰 준비가되지 않았습니다. 그것은 late_check(개념이 호출 될 때까지 확인되지 않은) 더 많은 것들을 필요 로합니다. 더 간단하게 모든 것을 버리고 단일 람다를 고수하는 것이 었습니다.

그러나 C ++ 0x에서 개념을 제거하면 다형성 람다는 다시 간단한 제안이됩니다. 그러나 이에 대한 제안을 찾을 수 없습니다. :(


C ++ 11 람다는 다른 답변에서 설명한 것처럼 템플릿을 만들 수 없지만 decltype()템플릿 클래스 또는 함수 내에서 람다를 사용할 때 도움이되는 것으로 보입니다.

#include <iostream>
#include <string>

using namespace std;

template<typename T>
void boring_template_fn(T t){
    auto identity = [](decltype(t) t){ return t;};
    std::cout << identity(t) << std::endl;
}

int main(int argc, char *argv[]) {
    std::string s("My string");
    boring_template_fn(s);
    boring_template_fn(1024);
    boring_template_fn(true);
}

인쇄물:

My string
1024
1

I've found this technique is helps when working with templated code but realize it still means lambdas themselves can't be templated.


In C++11, lambda functions can not be templated, but in the next version of the ISO C++ Standard (often called C++14), this feature will be introduced. [Source]

Usage example:

auto get_container_size = [] (auto container) { return container.size(); };

Note that though the syntax uses the keyword auto, the type deduction will not use the rules of auto type deduction, but instead use the rules of template argument deduction. Also see the proposal for generic lambda expressions(and the update to this).


I am aware that this question is about C++11. However, for those who googled and landed on this page, templated lambdas are now supported in C++14 and go by the name Generic Lambdas.

[info] Most of the popular compilers support this feature now. Microsoft Visual Studio 2015 supports. Clang supports. GCC supports.


I wonder what about this:

template <class something>
inline std::function<void()> templateLamda() {
  return [](){ std::cout << something.memberfunc() };
}

I used similar code like this, to generate a template and wonder if the compiler will optimize the "wrapping" function out.


Have a look at Boost.Phoenix for polymorphic lambdas: http://www.boost.org/doc/libs/1_44_0/libs/spirit/phoenix/doc/html/index.html Does not require C++0x, by the way :)


There is a gcc extension which allows lambda templates:

// create the widgets and set the label
base::for_each(_widgets, [] <typename Key_T, typename Widget_T>
                         (boost::fusion::pair<Key_T, Widget_T*>& pair) -> void {
                             pair.second = new Widget_T();
                             pair.second->set_label_str(Key_T::label);
                          }
              );

where _widgets is a std::tuple< fusion::pair<Key_T, Widget_T>... >


Here is one solution that involves wrapping the lamba in a structure:

template <typename T>                                                   
struct LamT                                                             
{                                                                       
   static void Go()                                                     
   {                                                                    
      auto lam = []()                                                   
      {                                                                 
         T var;                                                         
         std::cout << "lam, type = " << typeid(var).name() << std::endl;
      };                                                                

      lam();                                                            
   }                                                                    
};   

To use do:

LamT<int>::Go();  
LamT<char>::Go(); 
#This prints 
lam, type = i
lam, type = c

The main issue with this (besides the extra typing) you cannot embed this structure definition inside another method or you get (gcc 4.9)

error: a template declaration cannot appear at block scope

I also tried doing this:

template <typename T> using LamdaT = decltype(                          
   [](void)                                                          
   {                                                                 
       std::cout << "LambT type = " << typeid(T).name() << std::endl;  
   });

With the hope that I could use it like this:

LamdaT<int>();      
LamdaT<char>();

But I get the compiler error:

error: lambda-expression in unevaluated context

So this doesn't work ... but even if it did compile it would be of limited use because we would still have to put the "using LamdaT" at file scope (because it is a template) which sort of defeats the purpose of lambdas.


I'm not sure why nobody else has suggested this, but you can write a templated function that returns lambda functions. The following solved my problem, the reason I came to this page:

template <typename DATUM>
std::function<double(DATUM)> makeUnweighted() {
  return [](DATUM datum){return 1.0;};
}

Now whenever I want a function that takes a given type of argument (e.g. std::string), I just say

auto f = makeUnweighted<std::string>()

and now f("any string") returns 1.0.

That's an example of what I mean by "templated lambda function." (This particular case is used to automatically provide an inert weighting function when somebody doesn't want to weight their data, whatever their data might be.)


I've been playing with the latest clang version 5.0.1 compiling with the -std=c++17 flag and there is now some nice support for auto type parameters for lambdas:

#include <iostream>
#include <vector>
#include <stdexcept>

int main() {
    auto slice = [](auto input, int beg, int end) {
        using T = decltype(input);
        const auto size = input.size();
        if (beg > size || end > size || beg < 0 || end < 0) {
            throw std::out_of_range("beg/end must be between [0, input.size())");
        }
        if (beg > end) {
            throw std::invalid_argument("beg must be less than end");
        }
        return T(input.begin() + beg, input.begin() + end);
    };
    auto v = std::vector<int> { 1,2,3,4,5 };
    for (auto e : slice(v, 1, 4)) {
        std::cout << e << " ";
    }
    std::cout << std::endl;
}

참고URL : https://stackoverflow.com/questions/3575901/can-lambda-functions-be-templated

반응형