2016-08-03 5 views
1

, 나는 다음과 같은 자바 코드가 있습니다java.util.function.Consumer와 동일한 C++은 무엇입니까? 예를 들어

import java.util.function.Consumer; 

public class Main { 
    public static void main(String[] args) { 
    Consumer<String> c = (x) -> System.out.println(x.toLowerCase()); 
    c.accept("Java2s.com"); 
    } 
} 

무엇 C++ 상응하는 것?

+1

이와 비슷한 것이 복잡한 것 같습니까? – mash

+3

어쩌면? – Galik

+0

@Galik : 완벽하지만 자동으로 사용할 수있을 것 같아. "std :: function c = [] (auto s) {/*...*/} 두 곳에서 : auto c = [] (자동 x) {std :: cout << x << std :: endl; }; –

답변

1

정말 accept 가면. 당신은 또한을 구현할 수 :

#include <functional> 
#include <iostream> 
#include <string> 

template <class Food> 
class Consumer { 
private: 
    std::function<void(Food)> consume_; 

public: 
    template <class Eater> 
    Consumer<Food>(Eater consume) : consume_(consume){}; 

    void accept(Food food) { consume_(food); } 
}; 

// Usage 
int main() { 
    Consumer<const std::string&> consumer([](
     const std::string& out) { std::cout << out << '\n'; }); 
    consumer.accept("My lovley string."); 
    consumer.accept("Will be eaten!"); 
} 

또는 당신도 할 수 :

template <class Food> 
class Consumer { 
public: 
    std::function<void(Food)> accept; 

    template <class Eater> 
    Consumer<Food>(Eater consume) : accept(consume){}; 
}; 

당신이 즉시 accept을 교환 할 수 있도록하려면.

즉, 왜 소비자가 Java에 존재하는지 이해할 수 없습니다.

4

std::function<void(const std::string&)>을 사용하십시오.

당신은 함수 포인터에서이 인스턴스를 초기화하거나 할 수 람다 예에서 :

void foo(const std::string &s) { 
    std::cout << s << std::endl; 
} 

// later 
std::function<void(const std::string &)> c = foo; 
c("Java2s.com"); 

또는

std::function<void(const std::string &)> c = [](const std::string &) { 
    std::cout << s << std::endl; 
}; 
c("Java2s.com"); 
나는 당신이 필요로하는 기능이 특징을 기반으로 추측 벤처 것
0

람다 식가 제공합니다.

C++ 11은 람다 식 표현을 지원하며보다 일반적인 수준의 다음 코드는 사용자가 게시 한 코드를 제공합니다.

auto algorithm = [&](double x, double m, double b) -> double 
    { 
    return m*x+b; 
    }; 

int a=algorithm(1,2,3), b=algorithm(4,5,6); 
1

자바에서 Consumer이 사용되는 방법에 대한보다 완전한 예를 살펴 보겠습니다. 예를 들어, 트리의 노드를 출력, 우리는이 code from CodeReview.se 같은이있을 수 있습니다

C++에서
import java.util.function.Consumer; 

public static void preOrderTraversal(TreeViewItem treeNode,    
            Consumer<TreeViewItem> action) { 
    action.accept(treeNode); 
    for (TreeViewItem child : treeNode.getItems()) { 
     preOrderTraversal(child, action); 
    } 
} 

// Call that code with 
preOrderTraversal(rootNode, (TreeViewItem node) -> System.out.println(node.getText())); 

은, 몇 사람이 할 std::function를 사용을하지만, 적어도 내 의견으로는 일반적으로 실수가. 대신 C++의 템플릿 기능이 Java generics보다 훨씬 일반화되어 있으므로 Consumer에 대한 템플릿 매개 변수를 사용할 수 있습니다.

우리는 일반적으로 C++에서 연산자 오버로딩을 지원하므로 함수처럼 작동하는 무언가를 전달하고자 할 때 일반적으로 함수 호출 구문을 사용하여 호출 할 수 있습니다. 기능 같은 것은 (함수에 대한 포인터, 또는 람다에서 폐쇄 등 수 있습니다) : 자바 코드와 같은

template <class Item, class Consumer> 
void preOrderTraverse(Item i, Consumer action) { 
    action(item); 
    for (auto & child : item->getChildren()) 
     preOrderTraverse(child, action); 
} 

많은, 우리는 람다 식으로 작업을 정의 할 수 있습니다 :

preOrderTraverse(rootNode, [](auto node) { std::cout << node->getText(); }); 

간단히 말하면, std::function에 대한 매개 변수 형식 (최소한 비 가상 함수)은 C++에서 실수입니다. 이러한 경우 유형을 대신 템플리트 매개 변수로 전달해야합니다. std::function은 일반적으로 (예를 들어) 함수와 유사한 객체를 받아 들여 저장하고 나중에 호출해야하는 경우를 대비하여 예약됩니다.매개 변수 유형은 여전히 ​​템플리트 매개 변수 여야하지만 우리가 저장하는 객체는 합리적으로 std::function이 될 수 있습니다. 가상 수있는 기능과 같은 일반적인 기능을 통과해야하는 경우 가상 함수가 템플릿이 될 수 없기 때문에


1. 거의 유일한 실제 선택은 std::function을 사용하는 것입니다 (또는 당신 자신의 것과 비슷한 것을 만들어내는 것은 실제적인 개선이 아닐 것이다).

+0

'std :: function'은 템플릿이 될 수 없기 때문에'virtual' 함수의 인자로 예외가 될 것입니다. – MSalters

+0

@MSalters : 음 ... 그래, 그 얘기를 해야겠다. –