C ++ 11에는 람다 함수를 템플릿으로 만드는 방법이 있습니까? 아니면 템플릿으로 지정하기에는 너무 구체적입니까?
나는 대신 고전적인 템플릿 클래스 / functor를 정의 할 수 있다는 것을 이해하지만 질문은 더 비슷합니다 : 언어가 람다 함수를 템플릿 할 수 있습니까?
C ++ 11에는 람다 함수를 템플릿으로 만드는 방법이 있습니까? 아니면 템플릿으로 지정하기에는 너무 구체적입니까?
나는 대신 고전적인 템플릿 클래스 / functor를 정의 할 수 있다는 것을 이해하지만 질문은 더 비슷합니다 : 언어가 람다 함수를 템플릿 할 수 있습니까?
답변:
업데이트 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
이 기술은 템플릿 코드로 작업 할 때 도움이되지만 여전히 람다 자체를 템플릿으로 만들 수 없다는 것을 알고 있습니다.
T
decltype(t)
이 예제 대신 잘 작동합니다 .
C ++ 11에서는 람다 함수를 템플릿으로 만들 수 없지만 다음 버전의 ISO C ++ 표준 (일반적으로 C ++ 14)에서는이 기능이 도입됩니다. [출처]
사용 예 :
auto get_container_size = [] (auto container) { return container.size(); };
구문에서 keyword를 사용하지만 auto
유형 공제는 유형 공제 규칙을 사용하지 auto
않고 대신 템플리트 인수 공제 규칙을 사용합니다. 또한 일반적인 람다 식 제안 (및 이에 대한 업데이트) 을 참조하십시오 .
auto
유형 공제 규칙은 template
함수 인수 공제 규칙과 동일하게 정의됩니다 .
나는 이것에 대해 궁금합니다.
template <class something>
inline std::function<void()> templateLamda() {
return [](){ std::cout << something.memberfunc() };
}
비슷한 코드를 사용하여 템플릿을 생성하고 컴파일러가 "래핑"기능을 최적화하는지 궁금합니다.
: 다형성 람다에 대한 Boost.Phoenix에서 찾아 보게 http://www.boost.org/doc/libs/1_44_0/libs/spirit/phoenix/doc/html/index.html 에 의해, C ++ 0X가 필요하지 않습니다를 방법 :)
람다 템플릿 을 허용 하는 gcc 확장 이 있습니다 .
// 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);
}
);
어디 _widgets
있어std::tuple< fusion::pair<Key_T, Widget_T>... >
나는 플래그로 version 5.0.1
컴파일 하는 최신 clang을 가지고 놀고 -std=c++17
있었고 이제 람다에 대한 자동 유형 매개 변수에 대한 훌륭한 지원이 있습니다.
#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;
}
다음은 람 바를 구조로 감싸는 솔루션입니다.
template <typename T>
struct LamT
{
static void Go()
{
auto lam = []()
{
T var;
std::cout << "lam, type = " << typeid(var).name() << std::endl;
};
lam();
}
};
사용하려면 :
LamT<int>::Go();
LamT<char>::Go();
#This prints
lam, type = i
lam, type = c
이것에 대한 주요 문제 (추가 타이핑 제외)는이 구조 정의를 다른 메소드에 포함시킬 수 없거나 얻을 수 없습니다 (gcc 4.9)
error: a template declaration cannot appear at block scope
나는 또한 이것을 시도했다 :
template <typename T> using LamdaT = decltype(
[](void)
{
std::cout << "LambT type = " << typeid(T).name() << std::endl;
});
다음과 같이 사용할 수 있기를 바랍니다.
LamdaT<int>();
LamdaT<char>();
그러나 컴파일러 오류가 발생합니다.
error: lambda-expression in unevaluated context
그래서 이것은 작동하지 않습니다 ...하지만 컴파일 된 경우에도 "LamdaT 사용"을 파일 범위 (템플리트이기 때문에)에 배치해야하기 때문에 사용이 제한적입니다. 람다.
왜 아무도 이것을 제안하지 않았는지 모르겠지만 람다 함수를 반환하는 템플릿 함수를 작성할 수 있습니다. 다음은 내 문제,이 페이지에 온 이유를 해결했습니다.
template <typename DATUM>
std::function<double(DATUM)> makeUnweighted() {
return [](DATUM datum){return 1.0;};
}
이제 주어진 유형의 인수를 취하는 함수를 원할 때마다 (예 : std::string
), 난 그냥 말
auto f = makeUnweighted<std::string>()
그리고 지금 f("any string")
반환합니다 1.0
.
이것이 "템플릿 된 람다 함수"의 의미에 대한 예입니다. (이 특별한 경우는 데이터에 관계없이 누군가가 데이터에 가중치를 부여하지 않으려는 경우 자동으로 비활성 가중치 기능을 제공하는 데 사용됩니다.)